-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathASCoalescingOperationQueue.m
66 lines (52 loc) · 1.93 KB
/
ASCoalescingOperationQueue.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#import "ASCoalescingOperationQueue.h"
@implementation ASCoalescingOperationQueue {
dispatch_queue_t executionQueue;
// Access to nextUpBlock is synchronized through nextUpQueue
dispatch_queue_t nextUpQueue;
dispatch_block_t nextUpBlock;
}
- (id)initWithQueue:(dispatch_queue_t)theExecutionQueue {
if (!(self = [super init]))
return nil;
executionQueue = theExecutionQueue;
nextUpQueue = dispatch_queue_create("at.appscape.ASCoalescingOperationQueue.nextUpQueue", DISPATCH_QUEUE_SERIAL);
if (!nextUpQueue) { dispatch_release(executionQueue); return nil; }
dispatch_sync(nextUpQueue, ^{
nextUpBlock = nil;
});
return self;
}
- (void)dealloc {
dispatch_release(nextUpQueue);
dispatch_release(executionQueue);
}
+ (id)coalescingOperationQueue {
dispatch_queue_t theExecutionQueue = dispatch_queue_create("at.appscape.ASCoalescingOperationQueue.executionQueue", DISPATCH_QUEUE_SERIAL);
if (!theExecutionQueue) return nil;
return [[self alloc] initWithQueue:theExecutionQueue];
}
+ (id)coalescingOperationQueueUsingMainQueue {
return [[self alloc] initWithQueue:dispatch_get_main_queue()];
}
+ (id)coalescingOperationQueueUsingQueue:(dispatch_queue_t)theQueue {
dispatch_retain(theQueue);
return [[self alloc] initWithQueue:theQueue];
}
- (void)performBlock:(dispatch_block_t)submittedBlock {
dispatch_async(nextUpQueue, ^{
dispatch_block_t previouslySubmittedBlock = nextUpBlock;
nextUpBlock = submittedBlock;
if (!previouslySubmittedBlock) {
dispatch_async(executionQueue, ^{
__block dispatch_block_t blockToExecute = nil;
dispatch_sync(nextUpQueue, ^{
blockToExecute = nextUpBlock;
nextUpBlock = nil;
});
if (blockToExecute)
blockToExecute();
});
}
});
}
@end