]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/NSOperationCategories.m
Security-59306.61.1.tar.gz
[apple/security.git] / keychain / ckks / NSOperationCategories.m
1 /*
2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import <Foundation/Foundation.h>
25 #import "keychain/ckks/NSOperationCategories.h"
26 #import "keychain/ot/ObjCImprovements.h"
27 #import "utilities/debugging.h"
28
29 @implementation NSOperation (CKKSUsefulPrintingOperation)
30 - (NSString*)selfname {
31 if(self.name) {
32 return [NSString stringWithFormat: @"%@(%@)", NSStringFromClass([self class]), self.name];
33 } else {
34 return NSStringFromClass([self class]);
35 }
36 }
37
38 -(void)linearDependencies: (NSHashTable*) collection {
39 @synchronized(collection) {
40 for(NSOperation* existingop in collection) {
41 if(existingop == self) {
42 // don't depend on yourself
43 continue;
44 }
45 #if DEBUG
46 secnotice("ckks-operation", "adding dependency of %@ on %@", self, existingop);
47 #endif
48 [self addDependency: existingop];
49 }
50 [collection addObject:self];
51 }
52 }
53
54 -(void)linearDependenciesWithSelfFirst: (NSHashTable*) collection {
55 @synchronized(collection) {
56 for(NSOperation* existingop in collection) {
57 if(existingop == self) {
58 // don't depend on yourself
59 continue;
60 }
61
62 if([existingop isPending]) {
63 [existingop addDependency: self];
64 if([existingop isPending]) {
65 // Good, we're ahead of this one.
66 } else {
67 // It started before we told it to wait on us. Reverse the dependency.
68 [existingop removeDependency: self];
69 [self addDependency:existingop];
70 }
71 } else {
72 // Not a pending op? We depend on it.
73 [self addDependency: existingop];
74 }
75 }
76 [collection addObject:self];
77 }
78 }
79
80 -(NSString*)pendingDependenciesString:(NSString*)prefix {
81 NSArray* dependencies = [self.dependencies copy];
82 dependencies = [dependencies objectsAtIndexes: [dependencies indexesOfObjectsPassingTest: ^BOOL (id obj,
83 NSUInteger idx,
84 BOOL* stop) {
85 return [obj isFinished] ? NO : YES;
86 }]];
87
88 if(dependencies.count == 0u) {
89 return @"";
90 }
91
92 return [NSString stringWithFormat: @"%@%@", prefix, [dependencies componentsJoinedByString: @", "]];
93 }
94
95 - (NSString*)description {
96 NSString* state = ([self isFinished] ? @"finished" :
97 [self isCancelled] ? @"cancelled" :
98 [self isExecuting] ? @"executing" :
99 [self isReady] ? @"ready" :
100 @"pending");
101
102 return [NSString stringWithFormat: @"<%@: %@%@>", [self selfname], state, [self pendingDependenciesString: @" dep:"]];
103 }
104 - (NSString*)debugDescription {
105 NSString* state = ([self isFinished] ? @"finished" :
106 [self isCancelled] ? @"cancelled" :
107 [self isExecuting] ? @"executing" :
108 [self isReady] ? @"ready" :
109 @"pending");
110
111 return [NSString stringWithFormat: @"<%@ (%p): %@%@>", [self selfname], self, state, [self pendingDependenciesString: @" dep:"]];
112 }
113
114 - (BOOL)isPending {
115 return (!([self isExecuting] || [self isFinished] || [self isCancelled])) ? YES : NO;
116 }
117
118 - (void)addNullableDependency: (NSOperation*) op {
119 if(op) {
120 [self addDependency:op];
121 }
122 }
123
124 - (void)removeDependenciesUponCompletion
125 {
126 WEAKIFY(self);
127 self.completionBlock = ^{
128 STRONGIFY(self);
129 for (NSOperation *op in self.dependencies) {
130 [self removeDependency:op];
131 }
132 };
133 }
134
135 @end
136
137 @implementation NSBlockOperation (CKKSUsefulConstructorOperation)
138 +(instancetype)named: (NSString*)name withBlock: (void(^)(void)) block {
139 // How many blocks could a block block if a block could block blocks?
140 NSBlockOperation* blockOp = [NSBlockOperation blockOperationWithBlock: block];
141 blockOp.name = name;
142 return blockOp;
143 }
144 @end