#import <Foundation/Foundation.h>

@interface MyOperation : NSOperation
{
  BOOL        executing;
  BOOL        finished;
}
- (void)completeOperation;
@end

@implementation MyOperation

- (id)init
{
  self = [super init];
  if (self) {
    executing = NO;
    finished = NO;
  }
  return self;
}

- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return executing; }
- (BOOL)isFinished { return finished; }

- (void)main
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    
    // Do the main work of the operation here.
    long i;
    double a = 1.0;
    printf("starting\n");
    for (i = 0; i < 10000000000; ++i)
      a += 1.0;
    printf("ending: %lf\n", a);
    
    [self completeOperation];
    [pool release];
}

- (void)start
{
  // 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;
    }
  
  // If the operation is not canceled, begin executing the task.
  [self willChangeValueForKey:@"isExecuting"];
  [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
  executing = YES;
  [self didChangeValueForKey:@"isExecuting"];
}

- (void)completeOperation
{
  [self willChangeValueForKey:@"isFinished"];
  [self willChangeValueForKey:@"isExecuting"];
  
  executing = NO;
  finished = YES;
  
  [self didChangeValueForKey:@"isExecuting"];
  [self didChangeValueForKey:@"isFinished"];
}

@end

void testOperation()
{
  int i;
  NSOperationQueue *operationQueue = [NSOperationQueue new];                    
  [operationQueue setMaxConcurrentOperationCount: 12];

  for (i = 0; i < 10; ++i) {
    id io = [MyOperation new];
    [operationQueue addOperation: io];
  }
  [operationQueue waitUntilAllOperationsAreFinished];

  [operationQueue release];
}

void testThread()
{
  id io[5];
  NSThread *myThread[5];
  int i;

  for (i = 0; i < 5; ++i) {
    io[i] = [MyOperation new];

    myThread[i] = [[NSThread alloc] initWithTarget:io[i]
					  selector:@selector(main)
					    object:nil];
  }

  for (i = 0; i < 5; ++i)
    [myThread[i] start];  // Actually create the thread

  printf("waiting for thread to finish\n");
  BOOL done = YES;
  do {
    sleep(1);
    done = YES;
    for (i = 0; i < 5; ++i)
      if ([myThread[i] isExecuting]) done = NO;
  }
  while (!done);
}

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  testOperation();
  //testThread();

  //id io = [MyOperation new];
  //[io main];

  [pool drain];
  return 0;
}
