Created
March 19, 2014 18:39
-
-
Save claybridges/9648377 to your computer and use it in GitHub Desktop.
Possibly part of an answer to http://stackoverflow.com/questions/22509735.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface BarrierOperation : NSOperation | |
@end | |
@interface BarrierQueue : NSObject | |
- (void)addOperation:(NSOperation *)op; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "BarrierQueue.h" | |
#pragma mark - BarrierOperation | |
@implementation BarrierOperation | |
@end | |
#pragma mark - BarrierQueue | |
@interface BarrierQueue () | |
@property (nonatomic, strong) NSMutableArray *queueOfQueues; | |
@end | |
@implementation BarrierQueue | |
- (instancetype)init | |
{ | |
if ((self = [super init])) { | |
_queueOfQueues = [[NSMutableArray alloc] init]; | |
} | |
return self; | |
} | |
- (void)addOperation:(NSOperation *)op | |
{ | |
@synchronized (self) { | |
if ([op isKindOfClass:[BarrierOperation class]]) { | |
[self addBarrierOperation:(id)op]; | |
} else { | |
[[self addingQueue] addOperation:op]; | |
} | |
} | |
} | |
// Queue to which operations are still being added. | |
// Should only be accessed w/i a synch(self) block. | |
- (NSOperationQueue *)addingQueue | |
{ | |
if ([_queueOfQueues count] == 0) { | |
[_queueOfQueues addObject:[[NSOperationQueue alloc] init]]; | |
// start? | |
} | |
return [_queueOfQueues lastObject]; | |
} | |
- (void)popQueue | |
{ | |
@synchronized (self) { | |
NSAssert([_queueOfQueues count], @"should always be one to pop"); | |
[_queueOfQueues removeObjectAtIndex:0]; | |
if ([_queueOfQueues count]) { | |
// first queue is always running, all others suspended | |
[(NSOperationQueue *)_queueOfQueues[0] setSuspended:NO]; | |
} | |
} | |
} | |
// call only from @synchronized block in -addOperation: | |
- (void)addBarrierOperation:(BarrierOperation *)barrierOp | |
{ | |
[[self addingQueue] setSuspended:YES]; | |
for (NSOperation *op in [[self addingQueue] operations]) { | |
[barrierOp addDependency:op]; | |
} | |
[[self addingQueue] addOperation:barrierOp]; | |
// if you are free to set barrierOp.completionTask, you could skip popCallback and do that | |
__block typeof(self) weakSelf = self; | |
NSOperation *popCallback = [NSBlockOperation blockOperationWithBlock:^{ | |
[weakSelf popQueue]; | |
}]; | |
[popCallback addDependency:barrierOp]; | |
[[self addingQueue] addOperation:popCallback]; | |
[[self addingQueue] setSuspended:NO]; | |
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init]; | |
[opQueue setSuspended:YES]; | |
[_queueOfQueues addObject:opQueue]; // fresh empty queue to add to | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment