35#define USE_PTHREAD_ONCE (!OOLITE_WINDOWS)
45@interface NSThread (MethodsThatMayExistDependingOnSystem)
65- (void) queueResult:(
id<OOAsyncWorkTask>)task;
67- (void) noteTaskQueued:(
id<OOAsyncWorkTask>)task;
72#if !OO_HAVE_NSOPERATION
79- (void) queueTask:(NSNumber *)threadNumber;
91#if !OO_HAVE_NSOPERATION
95- (void) dispatchTask:(
id<OOAsyncWorkTask>)task;
101static NSLock *sInitLock =
nil;
107 NSCAssert(
sSingleton ==
nil,
@"Async Work Manager singleton not nil in one-time init");
109#if !OO_HAVE_NSOPERATION
116 sSingleton = [[OOManualDispatchAsyncWorkManager alloc] init];
124 OOLog(
@"asyncWorkManager.setUpDispatcher.failed",
@"%@",
@"***** FATAL ERROR: could not set up async work manager!");
128 OOLog(
@"asyncWorkManager.dispatchMethod",
@"Selected async work manager: %@", [
sSingleton class]);
132@implementation OOAsyncWorkManager
137 if (sInitLock ==
nil)
139 sInitLock = [[NSLock alloc] init];
140 NSAssert(sInitLock !=
nil,
@"Async Work Manager init failed");
149 static pthread_once_t once = PTHREAD_ONCE_INIT;
151 NSAssert(
sSingleton !=
nil,
@"Async Work Manager init failed");
157 NSAssert(
sSingleton !=
nil,
@"Async Work Manager init failed");
166+ (id) allocWithZone:(NSZone *)inZone
166+ (id) allocWithZone:(NSZone *)inZone {
…}
213- (void) waitForTaskToComplete:(
id<OOAsyncWorkTask>)task
216 [
NSException raise:NSInternalInconsistencyException format:@"%s called.", __PRETTY_FUNCTION__];
213- (void) waitForTaskToComplete:(
id<OOAsyncWorkTask>)task {
…}
227 if ((
self = [super
init]))
255 [_pendingOpsLock lock];
259 if (next ==
nil)
break;
261 [_pendingCompletableOperations removeObject:next];
262 [
next completeAsyncTask];
264 [_pendingOpsLock unlock];
268- (void) waitForTaskToComplete:(
id<OOAsyncWorkTask>)task
270 if (task ==
nil)
return;
273 NSParameterAssert([(
id)task respondsToSelector:
@selector(completeAsyncTask)]);
274 NSAssert1(![NSThread respondsToSelector:
@selector(isMainThread)] || [[NSThread
self] isMainThread],
@"%s can only be called from the main thread.", __PRETTY_FUNCTION__);
277 [_pendingOpsLock lock];
278 BOOL exists = [_pendingCompletableOperations containsObject:task];
279 if (exists) [_pendingCompletableOperations removeObject:task];
280 [_pendingOpsLock unlock];
289 [_pendingOpsLock lock];
290 [_pendingCompletableOperations removeObject:next];
291 [_pendingOpsLock unlock];
293 [
next completeAsyncTask];
295 }
while (next != task);
268- (void) waitForTaskToComplete:(
id<OOAsyncWorkTask>)task {
…}
299- (void) queueResult:(
id<OOAsyncWorkTask>)task
301 if ([task respondsToSelector:
@selector(completeAsyncTask)])
299- (void) queueResult:(
id<OOAsyncWorkTask>)task {
…}
308- (void) noteTaskQueued:(
id<OOAsyncWorkTask>)task
310 [_pendingOpsLock lock];
311 [_pendingCompletableOperations addObject:task];
312 [_pendingOpsLock unlock];
308- (void) noteTaskQueued:(
id<OOAsyncWorkTask>)task {
…}
327#if !OO_HAVE_NSOPERATION
328@implementation OOManualDispatchAsyncWorkManager
332 if ((
self = [super init]))
336 if (_taskQueue ==
nil)
343 NSUInteger threadCount, threadNumber = 1;
351 [NSThread detachNewThreadSelector:@selector(queueTask:) toTarget:
self withObject:[NSNumber numberWithInt:threadNumber++]];
352 }
while (--threadCount > 0);
363 [
super noteTaskQueued:task];
366 return [_taskQueue enqueue:task];
370- (void) queueTask:(NSNumber *)threadNumber
372 NSAutoreleasePool *rootPool =
nil, *pool =
nil;
374 rootPool = [[NSAutoreleasePool alloc] init];
376 [NSThread setThreadPriority:0.5];
377 [NSThread ooSetCurrentThreadName:[NSString stringWithFormat:@"OOAsyncWorkManager thread %@", threadNumber]];
381 pool = [[NSAutoreleasePool alloc] init];
383 id<OOAsyncWorkTask> task = [_taskQueue dequeue];
386 [task performAsyncTask];
388 @catch (
id exception) {}
389 [
self queueResult:task];
404@implementation OOOperationQueueAsyncWorkManager
406#if !OO_HAVE_NSOPERATION
409 if ([[NSUserDefaults standardUserDefaults] boolForKey:
@"disable-operation-queue-work-manager"])
return NO;
410 return [OONSInvocationOperationClass() class] != Nil;
417 if ((
self = [super
init]))
434 [_operationQueue release];
444 id operation = [[OONSInvocationOperationClass() alloc] initWithTarget:
self selector:@selector(dispatchTask:) object:task];
445 if (operation ==
nil)
return NO;
450 [_operationQueue addOperation:operation];
458- (void) dispatchTask:(
id<OOAsyncWorkTask>)task
462 [
task performAsyncTask];
464 @catch (
id exception) {}
458- (void) dispatchTask:(
id<OOAsyncWorkTask>)task {
…}
static void InitAsyncWorkManager(void)
NSUInteger OOCPUCount(void)
static OODebugMonitor * sSingleton
#define OOLogGenericSubclassResponsibility()
#define OOLog(class, format,...)
#define OONSOperationQueue
OOAsyncQueue * _readyQueue
NSMutableSet * _pendingCompletableOperations
void completePendingTasks()
void noteTaskQueued:(id< OOAsyncWorkTask > task)
void queueResult:(id< OOAsyncWorkTask > task)
void completePendingTasks()
OOAsyncWorkManager * sharedAsyncWorkManager()
OONSOperationQueue _operationQueue