2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #import <Foundation/Foundation.h>
25 #import "keychain/ckks/NSOperationCategories.h"
26 #import "keychain/ot/ObjCImprovements.h"
27 #import "utilities/debugging.h"
29 @implementation NSOperation (CKKSUsefulPrintingOperation)
30 - (NSString*)selfname {
32 return [NSString stringWithFormat: @"%@(%@)", NSStringFromClass([self class]), self.name];
34 return NSStringFromClass([self class]);
38 -(void)linearDependencies: (NSHashTable*) collection {
39 @synchronized(collection) {
40 for(NSOperation* existingop in collection) {
41 if(existingop == self) {
42 // don't depend on yourself
46 secnotice("ckks-operation", "adding dependency of %@ on %@", self, existingop);
48 [self addDependency: existingop];
50 [collection addObject:self];
54 -(void)linearDependenciesWithSelfFirst: (NSHashTable*) collection {
55 @synchronized(collection) {
56 for(NSOperation* existingop in collection) {
57 if(existingop == self) {
58 // don't depend on yourself
62 if([existingop isPending]) {
63 [existingop addDependency: self];
64 if([existingop isPending]) {
65 // Good, we're ahead of this one.
67 // It started before we told it to wait on us. Reverse the dependency.
68 [existingop removeDependency: self];
69 [self addDependency:existingop];
72 // Not a pending op? We depend on it.
73 [self addDependency: existingop];
76 [collection addObject:self];
80 -(NSString*)pendingDependenciesString:(NSString*)prefix {
81 NSArray* dependencies = [self.dependencies copy];
82 dependencies = [dependencies objectsAtIndexes: [dependencies indexesOfObjectsPassingTest: ^BOOL (id obj,
85 return [obj isFinished] ? NO : YES;
88 if(dependencies.count == 0u) {
92 return [NSString stringWithFormat: @"%@%@", prefix, [dependencies componentsJoinedByString: @", "]];
95 - (NSString*)description {
96 NSString* state = ([self isFinished] ? @"finished" :
97 [self isCancelled] ? @"cancelled" :
98 [self isExecuting] ? @"executing" :
99 [self isReady] ? @"ready" :
102 return [NSString stringWithFormat: @"<%@: %@%@>", [self selfname], state, [self pendingDependenciesString: @" dep:"]];
104 - (NSString*)debugDescription {
105 NSString* state = ([self isFinished] ? @"finished" :
106 [self isCancelled] ? @"cancelled" :
107 [self isExecuting] ? @"executing" :
108 [self isReady] ? @"ready" :
111 return [NSString stringWithFormat: @"<%@ (%p): %@%@>", [self selfname], self, state, [self pendingDependenciesString: @" dep:"]];
115 return (!([self isExecuting] || [self isFinished] || [self isCancelled])) ? YES : NO;
118 - (void)addNullableDependency: (NSOperation*) op {
120 [self addDependency:op];
124 - (void)removeDependenciesUponCompletion
127 self.completionBlock = ^{
129 for (NSOperation *op in self.dependencies) {
130 [self removeDependency:op];
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];