Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1397 from maicki/ASRunLoopQueueContinueProcessing
Browse files Browse the repository at this point in the history
[ASRunLoopQueue] Add custom run loop source to signal if jobs are still enqueued, to guarantee another runloop turn.
  • Loading branch information
appleguy committed Mar 18, 2016
2 parents c8cbd2e + 14b9df3 commit 0745eab
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions AsyncDisplayKit/ASRunLoopQueue.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@
#import "ASRunLoopQueue.h"
#import "ASThread.h"

#import <cstdlib>
#import <deque>

static void runLoopSourceCallback(void *info) {
// No-op
}

@interface ASRunLoopQueue () {
CFRunLoopRef _runLoop;
CFRunLoopObserverRef _runLoopObserver;
CFRunLoopSourceRef _runLoopSource;
std::deque<id> _internalQueue;
ASDN::RecursiveMutex _internalQueueLock;
}
Expand All @@ -36,12 +42,26 @@ - (instancetype)initWithRunLoop:(CFRunLoopRef)runloop andHandler:(void(^)(id deq
};
_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 = (CFRunLoopSourceContext *)calloc(1, sizeof(CFRunLoopSourceContext));
runLoopSourceContext->perform = runLoopSourceCallback;
_runLoopSource = CFRunLoopSourceCreate(NULL, 0, runLoopSourceContext);
CFRunLoopAddSource(runloop, _runLoopSource, kCFRunLoopCommonModes);
free(runLoopSourceContext);
}
return self;
}

- (void)dealloc
{
if (CFRunLoopContainsSource(_runLoop, _runLoopSource, kCFRunLoopCommonModes)) {
CFRunLoopRemoveSource(_runLoop, _runLoopSource, kCFRunLoopCommonModes);
}
CFRelease(_runLoopSource);
_runLoopSource = nil;

if (CFRunLoopObserverIsValid(_runLoopObserver)) {
CFRunLoopObserverInvalidate(_runLoopObserver);
}
Expand Down Expand Up @@ -103,6 +123,9 @@ - (void)enqueue:(id)object

if (!foundObject) {
_internalQueue.push_back(object);

CFRunLoopSourceSignal(_runLoopSource);
CFRunLoopWakeUp(_runLoop);
}
}

Expand Down

0 comments on commit 0745eab

Please sign in to comment.