From d1756baae7e4f9de2d8a90d4988b6970901e1acf Mon Sep 17 00:00:00 2001 From: Michael Schneider Date: Fri, 18 Mar 2016 14:02:27 -0700 Subject: [PATCH] Add custom run loop source to signal if new jobs are enqueued in ASRunLoopQueue It is not guaranteed that the runloop will turn if it has no scheduled work, and this causes processing of the queue to stop. Attaching a custom loop source to the run loop and signal it if new work needs to be done --- AsyncDisplayKit/ASRunLoopQueue.mm | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/AsyncDisplayKit/ASRunLoopQueue.mm b/AsyncDisplayKit/ASRunLoopQueue.mm index 2eb3420e18..b27a745279 100644 --- a/AsyncDisplayKit/ASRunLoopQueue.mm +++ b/AsyncDisplayKit/ASRunLoopQueue.mm @@ -11,9 +11,14 @@ #import +static void runLoopSourceCallback(void *info) { + // No-op +} + @interface ASRunLoopQueue () { CFRunLoopRef _runLoop; CFRunLoopObserverRef _runLoopObserver; + CFRunLoopSourceRef _runLoopSource; std::deque _internalQueue; ASDN::RecursiveMutex _internalQueueLock; } @@ -36,12 +41,24 @@ }; _runLoopObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, handlerBlock); CFRunLoopAddObserver(_runLoop, _runLoopObserver, kCFRunLoopCommonModes); + + // It is not guaranteed that the runloop will turn if it has no scheduled work, and this causes processing of + // 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 = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &runLoopSourceCallback}; + _runLoopSource = CFRunLoopSourceCreate(NULL, 0, &runLoopSourceContext); + CFRunLoopAddSource(runloop, _runLoopSource, kCFRunLoopCommonModes); } return self; } - (void)dealloc { + if (CFRunLoopContainsSource(_runLoop, _runLoopSource, kCFRunLoopCommonModes)) { + CFRunLoopRemoveSource(_runLoop, _runLoopSource, kCFRunLoopCommonModes); + } + CFRelease(_runLoopSource); + _runLoopSource = nil; + if (CFRunLoopObserverIsValid(_runLoopObserver)) { CFRunLoopObserverInvalidate(_runLoopObserver); } @@ -103,6 +120,9 @@ if (!foundObject) { _internalQueue.push_back(object); + + CFRunLoopSourceSignal(_runLoopSource); + CFRunLoopWakeUp(_runLoop); } }