Skip to content

Instantly share code, notes, and snippets.

@SiarheiFedartsou
Created November 11, 2015 14:53
Show Gist options
  • Save SiarheiFedartsou/0e04557c9025d235a703 to your computer and use it in GitHub Desktop.
Save SiarheiFedartsou/0e04557c9025d235a703 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <libkern/OSAtomic.h>
typedef struct {
BOOL scheduled;
OSSpinLock lock;
} PAScheduleOnceToken;
static char PAScheduleOnceTokenKey;
static void PAScheduleOnce(dispatch_queue_t queue, void (^block)())
{
PAScheduleOnceToken* tokenPointer = (PAScheduleOnceToken*)dispatch_queue_get_specific(queue, &PAScheduleOnceTokenKey);
if (!tokenPointer) {
tokenPointer = (PAScheduleOnceToken*)malloc(sizeof(PAScheduleOnceToken));
*tokenPointer = (PAScheduleOnceToken){.scheduled = NO, .lock = OS_SPINLOCK_INIT};
}
if (tokenPointer && block) {
OSSpinLockLock(&tokenPointer->lock);
BOOL scheduled = tokenPointer->scheduled;
OSSpinLockUnlock(&tokenPointer->lock);
if (!scheduled) {
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
if (timer) {
OSSpinLockLock(&tokenPointer->lock);
tokenPointer->scheduled = YES;
OSSpinLockUnlock(&tokenPointer->lock);
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC), 0 * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10);
dispatch_source_set_event_handler(timer, ^ {
block();
dispatch_source_cancel(timer);
OSSpinLockLock(&tokenPointer->lock);
tokenPointer->scheduled = NO;
OSSpinLockUnlock(&tokenPointer->lock);
});
dispatch_resume(timer);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment