From b3e98e9f5fc3a99ee674d54b1920317b5f42a3d6 Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Mon, 21 Mar 2016 16:58:39 -0700 Subject: [PATCH] If the queue is not fully drained yet force another run loop to process next batch of items --- AsyncDisplayKit/ASRunLoopQueue.mm | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/AsyncDisplayKit/ASRunLoopQueue.mm b/AsyncDisplayKit/ASRunLoopQueue.mm index 8519a61f13..a18f7a8a70 100644 --- a/AsyncDisplayKit/ASRunLoopQueue.mm +++ b/AsyncDisplayKit/ASRunLoopQueue.mm @@ -12,8 +12,13 @@ #import #import +#define ASRunLoopQueueLoggingEnabled 0 + static void runLoopSourceCallback(void *info) { // No-op +#if ASRunLoopQueueLoggingEnabled + NSLog(@"<%@> - Called runLoopSourceCallback", info); +#endif } @interface ASRunLoopQueue () { @@ -22,6 +27,10 @@ static void runLoopSourceCallback(void *info) { CFRunLoopSourceRef _runLoopSource; std::deque _internalQueue; ASDN::RecursiveMutex _internalQueueLock; + +#if ASRunLoopQueueLoggingEnabled + NSTimer *_runloopQueueLoggingTimer; +#endif } @property (nonatomic, copy) void (^queueConsumer)(id dequeuedItem, BOOL isQueueDrained); @@ -47,9 +56,17 @@ static void runLoopSourceCallback(void *info) { // the queue to stop. Attaching a custom loop source to the run loop and signal it if new work needs to be done CFRunLoopSourceContext *runLoopSourceContext = (CFRunLoopSourceContext *)calloc(1, sizeof(CFRunLoopSourceContext)); runLoopSourceContext->perform = runLoopSourceCallback; +#if ASRunLoopQueueLoggingEnabled + runLoopSourceContext->info = (__bridge void *)self; +#endif _runLoopSource = CFRunLoopSourceCreate(NULL, 0, runLoopSourceContext); CFRunLoopAddSource(runloop, _runLoopSource, kCFRunLoopCommonModes); free(runLoopSourceContext); + +#if ASRunLoopQueueLoggingEnabled + _runloopQueueLoggingTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(checkRunLoop) userInfo:nil repeats:YES]; + [[NSRunLoop mainRunLoop] addTimer:_runloopQueueLoggingTimer forMode:NSRunLoopCommonModes]; +#endif } return self; } @@ -69,6 +86,13 @@ static void runLoopSourceCallback(void *info) { _runLoopObserver = nil; } +#if ASRunLoopQueueLoggingEnabled +- (void)checkRunLoop +{ + NSLog(@"<%@> - Jobs: %ld", self, _internalQueue.size()); +} +#endif + - (void)processQueue { std::deque itemsToProcess = std::deque(); @@ -102,6 +126,12 @@ static void runLoopSourceCallback(void *info) { self.queueConsumer(itemsToProcess[i], isQueueDrained); } } + + // If the queue is not fully drained yet force another run loop to process next batch of items + if (!isQueueDrained) { + CFRunLoopSourceSignal(_runLoopSource); + CFRunLoopWakeUp(_runLoop); + } } - (void)enqueue:(id)object