Skip to content

Instantly share code, notes, and snippets.

@Strilanc
Created October 22, 2013 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Strilanc/7094527 to your computer and use it in GitHub Desktop.
Save Strilanc/7094527 to your computer and use it in GitHub Desktop.
Using grand central dispatch to run a callback after a delay, with hacky partial cancellation. Cancelling allows the callback to be deallocated, but doesn't completely clean up what's in GCD.
+(void) runBlock:(VoidBlock)callback
afterDelay:(NSTimeInterval)delayInSeconds
unless:(TOCCancelToken*)unlessCancelledToken {
__block VoidBlock callbackForBlock = callback;
NSObject* lock = [NSObject new];
VoidBlock allowDeallocWrapper = ^{
VoidBlock callbackPeek;
@synchronized(lock) {
callbackPeek = callbackForBlock;
}
if (callbackPeek == nil) return; // cancelled
callbackPeek();
};
const int nanosPerSec = 1000*1000*1000;
// simplification: just assume the double to dispatch_time_t conversion is going to work
dispatch_time_t callTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds / nanosPerSec));
dispatch_after(callTime,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
allowDeallocWrapper);
// Simplification: assuming the cancellation token is not long lived (will discuss)
[unlessCancelledToken whenCancelledDo:^{
@synchronized(lock) {
callbackForBlock = nil;
}
}];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment