Reputation: 49085
I have some NSOperation
s in a dependency graph:
NSOperation *op1 = ...;
NSOperation *op2 = ...;
[op2 addDependency:op1];
Here's how I'm running them:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:op1];
[queue addOperation:op2];
Now I need to cancel them. How do I ensure that all the NSOperation
s in a dependency graph are cancelled, and that no other NSOperation
s are cancelled?
what I've tried:
Calling cancel
on either NSOperation
doesn't cancel the other (as far as I can tell):
[op1 cancel]; // doesn't cancel op2
// -- or --
[op2 cancel]; // doesn't cancel op1
Cancelling the queue would also cancel operations that aren't part of the dependency graph of op1
and op2
(if there are any such operations in the queue):
[queue cancelAllOperations];
So I solved this using a custom method that recursively looks through an NSOperation
's dependencies and cancels them. However, I'm not happy with this solution because I feel like I'm fighting the framework:
- (void)recursiveCancel:(NSOperation *)op
{
[op cancel];
for (NSOperation *dep in op.dependencies)
{
[self recursiveCancel:op];
}
}
Upvotes: 11
Views: 3483
Reputation: 30571
Sounds to me like you are trying to group operations together in the same queue. To achieve that it's best to split them up using a queue per group. So for each group create an NSOperation subclass in concurrent mode, include a queue, add each sub-operation to the queue. Override cancel and call [super cancel] then [self.queue cancelAllOperations].
A huge advantage of this approach is you can retry operations by adding again to the sub-queue, without affecting the order of the main queue.
Upvotes: 2
Reputation: 14010
There does not exist a notion of an NSOperation
automatically cancelling its dependencies. This is because multiple NSOperation
s may be dependent on the same other NSOperation
. The dependency relationship exists strictly to delay execution of a particular NSOperation
until all of its dependency NSOperation
s are complete.
You may consider writing a subclass of NSOperation
:
@interface NSOperationOneToOne : NSOperation
- (void)addOneToOneDependency:(NSOperation *)operation;
- (void)removeOneToOneDependency:(NSOperation *)operation;
@end
@implementation NSOperationOneToOne {
NSMutableArray *oneToOneDependencies;
}
- (void)addOneToOneDependency:(NSOperation *)operation {
[oneToOneDependencies addObject:operation];
[self addDependency:operation];
}
- (void)removeOneToOneDependency:(NSOperation *)operation {
[oneToOneDependencies removeObject:operation];
[self removeDependency:operation];
}
- (void)cancel {
[super cancel];
[oneToOneDependencies makeObjectsPerformSelector:@selector(cancel)];
}
@end
Note: The above code is not guaranteed to be bug-free.
Upvotes: 10