Skip to content

Instantly share code, notes, and snippets.

@swillits
Last active December 15, 2015 01:59
Show Gist options
  • Save swillits/5184433 to your computer and use it in GitHub Desktop.
Save swillits/5184433 to your computer and use it in GitHub Desktop.
Coalesced Blocks
@interface GCDCoalescent : NSObject
- (void)dispatchOn:(dispatch_queue_t)queue after:(double)seconds block:(dispatch_block_t)block;
@end
@implementation GCDCoalescent
{
uint64_t count;
}
- (void)dispatchOn:(dispatch_queue_t)queue after:(double)seconds block:(dispatch_block_t)block;
{
uint64_t eventNumber = __sync_add_and_fetch(&count, 1);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), queue, ^{
if (count > eventNumber) return;
block();
});
}
@end
@interface GCDCoalescer : NSObject
+ (GCDCoalescer *)shared;
- (void)dispatch:(NSString *)identifier on:(dispatch_queue_t)queue after:(double)seconds block:(dispatch_block_t)block;
@end
@implementation GCDCoalescer
{
NSLock * _lock;
NSMutableArray * _tags;
uint64_t * _counts;
uint64_t _numCounts;
uint64_t _capacity;
}
+ (GCDCoalescer *)shared;
{
static GCDCoalescer * shared = nil;
if (!shared) {
shared = [[GCDCoalescer alloc] init];
}
return shared;
}
- (id)init;
{
if (!(self = [super init])) {
return nil;
}
_tags = [[NSMutableArray alloc] init];
_lock = [[NSLock alloc] init];
_capacity = 16;
_counts = calloc(_capacity * sizeof(uint64_t), 1);
_numCounts = 0;
return self;
}
- (void)dealloc;
{
if (_counts) free(_counts);
[_tags release];
[_lock release];
[super dealloc];
}
- (void)dispatch:(NSString *)identifier on:(dispatch_queue_t)queue after:(double)seconds block:(dispatch_block_t)block;
{
NSUInteger index = [_tags indexOfObject:identifier];
if (index == NSNotFound) {
index = _numCounts;
if (_numCounts == _capacity) {
[_lock lock];
_capacity += 16;
_counts = realloc(_counts, sizeof(uint64_t) * _capacity);
[_lock unlock];
}
[_tags addObject:identifier];
_counts[index] = 0;
_numCounts++;
}
uint64_t eventNumber = __sync_add_and_fetch(_counts + index, 1);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), queue, ^{
uint64_t currentCount;
[_lock lock];
currentCount = _counts[index];
[_lock unlock];
if (currentCount > eventNumber) return;
block();
});
}
@end
@swillits
Copy link
Author

Pushed A 0 at 74.9
Pushed A 1 at 75.1
Pushed B 2 at 75.9
Pushed B 3 at 76.0
Fired A 1 at 76.1
Pushed B 4 at 76.3
Pushed B 5 at 76.6
Pushed B 6 at 76.8
Pushed B 7 at 77.2
Pushed A 8 at 77.5
Pushed A 9 at 77.7
Pushed A 10 at 77.8
Pushed A 11 at 78.0
Pushed A 12 at 78.2
Fired B 7 at 78.2
Pushed A 13 at 78.3
Pushed A 14 at 78.5
Pushed A 15 at 78.7
Pushed A 16 at 78.8
Pushed A 17 at 79.0
Fired A 17 at 80.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment