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]);
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
184- (oneway void) release
194- (NSUInteger) retainCount
207- (void) completePendingTasks
213- (void) waitForTaskToComplete:(
id<OOAsyncWorkTask>)task
216 [NSException raise:NSInternalInconsistencyException format:@"%s called.", __PRETTY_FUNCTION__];
227 if ((
self = [super init]))
231 if (_readyQueue ==
nil)
237 _pendingCompletableOperations = [[NSMutableSet alloc] init];
238 _pendingOpsLock = [[NSLock alloc] init];
240 if (_pendingCompletableOperations ==
nil || _pendingOpsLock ==
nil)
251- (void) completePendingTasks
255 [_pendingOpsLock lock];
258 next = [_readyQueue tryDequeue];
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];
288 next = [_readyQueue dequeue];
289 [_pendingOpsLock lock];
290 [_pendingCompletableOperations removeObject:next];
291 [_pendingOpsLock unlock];
293 [next completeAsyncTask];
295 }
while (next != task);
299- (void) queueResult:(
id<OOAsyncWorkTask>)task
301 if ([task respondsToSelector:
@selector(completeAsyncTask)])
303 [_readyQueue enqueue:task];
308- (void) noteTaskQueued:(
id<OOAsyncWorkTask>)task
310 [_pendingOpsLock lock];
311 [_pendingCompletableOperations addObject:task];
312 [_pendingOpsLock unlock];
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];
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]))
419 _operationQueue = [[OONSOperationQueueClass() alloc] init];
421 if (_operationQueue ==
nil)
434 [_operationQueue release];
444 id operation = [[OONSInvocationOperationClass() alloc] initWithTarget:self selector:@selector(dispatchTask:) object:task];
445 if (operation ==
nil)
return NO;
447 if (priority ==
kOOAsyncPriorityLow) [operation setQueuePriority:OONSOperationQueuePriorityLow];
448 else if (priority ==
kOOAsyncPriorityHigh) [operation setQueuePriority:OONSOperationQueuePriorityHigh];
450 [_operationQueue addOperation:operation];
453 [
super noteTaskQueued:task];
458- (void) dispatchTask:(
id<OOAsyncWorkTask>)task
462 [task performAsyncTask];
464 @catch (
id exception) {}
465 [
self queueResult:task];
static OOAsyncWorkManager * sSingleton
static void InitAsyncWorkManager(void)
NSUInteger OOCPUCount(void)
static OODebugMonitor * sSingleton
#define OOLogGenericSubclassResponsibility()
#define OOLog(class, format,...)
#define OONSOperationQueue
OOAsyncQueue * _readyQueue
NSMutableSet * _pendingCompletableOperations
OONSOperationQueue _operationQueue