2011-02-28 18:28:19 +00:00
|
|
|
#import <Foundation/NSArray.h>
|
|
|
|
#import <Foundation/NSLock.h>
|
|
|
|
#import <Foundation/NSOperation.h>
|
|
|
|
#import <Foundation/NSThread.h>
|
|
|
|
#import <Foundation/NSNotification.h>
|
|
|
|
#import <Foundation/NSAutoreleasePool.h>
|
|
|
|
#import "ObjectTesting.h"
|
|
|
|
|
|
|
|
// concurrent operation
|
|
|
|
@interface MyOperation : NSOperation
|
|
|
|
{
|
|
|
|
int calculation;
|
|
|
|
|
|
|
|
BOOL executing;
|
|
|
|
BOOL finished;
|
|
|
|
}
|
|
|
|
- (void) completeOperation;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation MyOperation
|
|
|
|
|
|
|
|
- (id) initWithValue: (int)aVal
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (self) {
|
|
|
|
calculation = aVal;
|
|
|
|
executing = NO;
|
|
|
|
finished = NO;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isConcurrent { return YES; }
|
|
|
|
- (BOOL) isExecuting { return executing; }
|
|
|
|
- (BOOL) isFinished { return finished; }
|
|
|
|
- (int) getCalculation { return calculation; }
|
|
|
|
|
|
|
|
- (void) main
|
|
|
|
{
|
|
|
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
[self willChangeValueForKey:@"isExecuting"];
|
|
|
|
executing = YES;
|
|
|
|
[self didChangeValueForKey:@"isExecuting"];
|
|
|
|
// Do the main work of the operation here.
|
|
|
|
calculation = 2 * calculation;
|
|
|
|
|
|
|
|
[self completeOperation];
|
|
|
|
[pool release];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) start
|
|
|
|
{
|
|
|
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
// Always check for cancellation before launching the task.
|
|
|
|
if ([self isCancelled])
|
|
|
|
{
|
|
|
|
// Must move the operation to the finished state if it is canceled.
|
|
|
|
[self willChangeValueForKey: @"isFinished"];
|
|
|
|
finished = YES;
|
|
|
|
[self didChangeValueForKey: @"isFinished"];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// As the operation is not canceled, begin executing the task.
|
|
|
|
[NSThread detachNewThreadSelector: @selector(main)
|
|
|
|
toTarget: self
|
|
|
|
withObject: nil];
|
|
|
|
[pool release];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) completeOperation
|
|
|
|
{
|
|
|
|
[self willChangeValueForKey: @"isFinished"];
|
|
|
|
[self willChangeValueForKey: @"isExecuting"];
|
|
|
|
|
|
|
|
executing = NO;
|
|
|
|
finished = YES;
|
|
|
|
|
|
|
|
[self didChangeValueForKey: @"isExecuting"];
|
|
|
|
[self didChangeValueForKey: @"isFinished"];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
id obj;
|
|
|
|
NSOperationQueue *q;
|
|
|
|
int i;
|
|
|
|
NSMutableArray *a;
|
|
|
|
|
2011-02-28 19:57:11 +00:00
|
|
|
START_SET("concurrent operations")
|
2011-02-28 18:28:19 +00:00
|
|
|
|
|
|
|
// single concurrent operation
|
|
|
|
obj = [[MyOperation alloc] initWithValue: 1];
|
|
|
|
q = [NSOperationQueue new];
|
|
|
|
[q addOperation: obj];
|
|
|
|
[q waitUntilAllOperationsAreFinished];
|
|
|
|
PASS(([obj isFinished] == YES), "operation ran");
|
|
|
|
PASS(([obj isExecuting] == NO), "operation is not executing");
|
|
|
|
PASS(([obj getCalculation] == 2), "operation was performed");
|
|
|
|
[obj release];
|
|
|
|
|
|
|
|
// multiple concurrent operations
|
|
|
|
[q setMaxConcurrentOperationCount: 10];
|
|
|
|
a = [NSMutableArray array];
|
|
|
|
for (i = 0; i < 5; ++i)
|
|
|
|
{
|
|
|
|
obj = [[MyOperation alloc] initWithValue: i];
|
|
|
|
[a addObject: obj];
|
|
|
|
[q addOperation: obj];
|
|
|
|
}
|
|
|
|
[q waitUntilAllOperationsAreFinished];
|
|
|
|
PASS(([obj isFinished] == YES), "operation ran");
|
|
|
|
PASS(([obj isExecuting] == NO), "operation is not executing");
|
|
|
|
|
|
|
|
for (i = 0; i < 5; ++i)
|
|
|
|
{
|
|
|
|
obj = [a objectAtIndex: i];
|
|
|
|
PASS(([obj getCalculation] == (2*i)), "operation was performed");
|
|
|
|
}
|
|
|
|
|
|
|
|
// multiple concurrent operations
|
|
|
|
[q setMaxConcurrentOperationCount: 5];
|
|
|
|
a = [NSMutableArray array];
|
|
|
|
for (i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
obj = [[MyOperation alloc] initWithValue: i];
|
|
|
|
[a addObject: obj];
|
|
|
|
}
|
|
|
|
[q addOperations: a waitUntilFinished: YES];
|
|
|
|
PASS(([obj isFinished] == YES), "operation ran");
|
|
|
|
PASS(([obj isExecuting] == NO), "operation is not executing");
|
|
|
|
|
|
|
|
for (i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
obj = [a objectAtIndex: i];
|
|
|
|
PASS(([obj getCalculation] == (2*i)), "operation was performed");
|
|
|
|
}
|
|
|
|
|
2011-02-28 19:57:11 +00:00
|
|
|
END_SET("concurrent operations")
|
2011-02-28 18:28:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|