// // BatchExample.m // // Created by Daniel Vollmer on 05.01.07. // Copyright [maven] heavy industries 2007 . All rights reserved. // #import #import "BatchExample.h" #import "SIWorkUnit.h" #import "SIWorkManager.h" @implementation BatchExample - (id)init { self = [super init]; if (self) { // NSLog(@"init: %@", self); // There should only be one SIWorkManager in your application. // You could for example create it in your NSDocumentController... _workManager = [[SIWorkManager alloc] init]; // create as many worker threads as cores // this lock is used for batch processing _processingLock = [[NSConditionLock alloc] initWithCondition:0]; } return self; } - (void)dealloc { // NSLog(@"dealloc: %@", self); [_processingLock release]; [_workManager release]; [super dealloc]; } // this will be called from another thread - (id)doSomethingSimple:(id)argument { NSNumber *expensiveToCreateObject; // NSLog is thread-safe NSLog(@"Got %@ as argument in thread %@.", argument, [NSThread currentThread]); // do work here expensiveToCreateObject = [[NSNumber alloc] initWithDouble:1.0]; return expensiveToCreateObject; // return work done } // this is called in the main-thread again - (id)finishedSomethingSimple:(id)result { NSLog(@"Received result %@.", result); [result release]; // usually, we add it to our UI } - (void)demonstrateSimple { int i; for (i = 0; i < 10; i++) { SIWorkUnit *wu = [[SIWorkUnit alloc] initWithTarget:self withSelector:@selector(doSomethingSimple:) withArgument:self withDidEndSelector:@selector(finishedSomethingSimple:)]; if (wu) { [_workManager addWorkUnit:wu isHighPriority:NO]; [wu release]; } } NSLog(@"Queued all jobs."); } // this will be called from another thread - (id)doSomethingBatch:(id)argument { // NSLog is thread-safe NSLog(@"Got %@ as argument in thread %@.", argument, [NSThread currentThread]); // do work here // [argument performThreadsafeExpensiveJob]; // notify main-thread that one more batch entry is done [_processingLock lock]; [_processingLock unlockWithCondition:[_processingLock condition] + 1]; return nil; // return work done } - (void)demonstrateBatch { const int numBatch = 10; int i; for (i = 0; i < numBatch; i++) { // didEndSelector would only be called after we unblock the main-thread and its NSRunLoop is called again SIWorkUnit *wu = [[SIWorkUnit alloc] initWithTarget:self withSelector:@selector(doSomethingBatch:) withArgument:self withDidEndSelector:NULL]; if (wu) { [_workManager addWorkUnit:wu isHighPriority:NO]; [wu release]; } } NSLog(@"Queued all jobs."); [_processingLock lockWhenCondition:numBatch]; [_processingLock unlockWithCondition:0]; // and reset to 0 for the next time NSLog(@"All jobs done."); } @end // run it int main (int argc, char** argv, char** env) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSArray *args = [[NSProcessInfo processInfo] arguments]; BatchExample *b = [[BatchExample alloc] init]; [b demonstrateSimple]; [b demonstrateBatch]; [b release]; [pool release]; return 0; }