00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 @import <Foundation/CPObject.j>
00023 @import "CPOperation.j"
00024 @import "CPInvocationOperation.j"
00025 @import "CPFunctionOperation.j"
00026
00027
00028 var cpOperationMainQueue = nil;
00029
00034 @implementation CPOperationQueue : CPObject
00035 {
00036 CPArray _operations;
00037 BOOL _suspended;
00038 CPString _name @accessors(property=name);
00039 CPTimer _timer;
00040 }
00041
00042 - (id)init
00043 {
00044 if (self = [super init])
00045 {
00046 _operations = [[CPArray alloc] init];
00047 _suspended = NO;
00048 _currentlyModifyingOps = NO;
00049 _timer = [CPTimer scheduledTimerWithTimeInterval:0.01
00050 target:self
00051 selector:@selector(_runNextOpsInQueue)
00052 userInfo:nil
00053 repeats:YES];
00054 }
00055 return self;
00056 }
00057
00058 - (void)_runNextOpsInQueue
00059 {
00060 if (!_suspended && [self operationCount] > 0)
00061 {
00062 var i = 0;
00063 for (i = 0; i < [_operations count]; i++)
00064 {
00065 var op = [_operations objectAtIndex:i];
00066 if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
00067 {
00068 [op start];
00069 }
00070 }
00071 }
00072 }
00073
00074 - (void)_enableTimer:(BOOL)enable
00075 {
00076 if (!enable)
00077 {
00078 if (_timer)
00079 {
00080 [_timer invalidate];
00081 _timer = nil;
00082 }
00083 }
00084 else
00085 {
00086 if (!_timer)
00087 {
00088 _timer = [CPTimer scheduledTimerWithTimeInterval:0.01
00089 target:self
00090 selector:@selector(_runNextOpsInQueue)
00091 userInfo:nil
00092 repeats:YES];
00093 }
00094 }
00095 }
00096
00101 - (void)addOperation:(CPOperation)anOperation
00102 {
00103 [self willChangeValueForKey:@"operations"];
00104 [self willChangeValueForKey:@"operationCount"];
00105 [_operations addObject:anOperation];
00106 [self _sortOpsByPriority:_operations];
00107 [self didChangeValueForKey:@"operations"];
00108 [self didChangeValueForKey:@"operationCount"];
00109 }
00110
00116 - (void)addOperations:(CPArray)ops waitUntilFinished:(BOOL)wait
00117 {
00118 if (ops)
00119 {
00120 if (wait)
00121 {
00122 [self _sortOpsByPriority:ops];
00123 [self _runOpsSynchronously:ops];
00124 }
00125
00126 [_operations addObjectsFromArray:ops];
00127 [self _sortOpsByPriority:_operations];
00128 }
00129 }
00130
00135 - (void)addOperationWithFunction:(JSObject)aFunction
00136 {
00137 [self addOperation:[CPFunctionOperation functionOperationWithFunction:aFunction]];
00138 }
00139
00140 - (CPArray)operations
00141 {
00142 return _operations;
00143 }
00144
00145 - (int)operationCount
00146 {
00147 if (_operations)
00148 {
00149 return [_operations count];
00150 }
00151
00152 return 0;
00153 }
00154
00158 - (void)cancelAllOperations
00159 {
00160 if (_operations)
00161 {
00162 var i = 0;
00163 for (i = 0; i < [_operations count]; i++)
00164 {
00165 [[_operations objectAtIndex:i] cancel];
00166 }
00167 }
00168 }
00169
00173 - (void)waitUntilAllOperationsAreFinished
00174 {
00175
00176 [self _enableTimer:NO];
00177 [self _runOpsSynchronously:_operations];
00178 if (!_suspended)
00179 {
00180 [self _enableTimer:YES];
00181 }
00182 }
00183
00184
00189 - (int)maxConcurrentOperationCount
00190 {
00191 return 1;
00192 }
00193
00198 - (void)setSuspended:(BOOL)suspend
00199 {
00200 _suspended = suspend;
00201 [self _enableTimer:!suspend];
00202 }
00203
00207 - (BOOL)isSuspended
00208 {
00209 return _suspended;
00210 }
00211
00212 - (void)_sortOpsByPriority:(CPArray)someOps
00213 {
00214 if (someOps)
00215 {
00216 [someOps sortUsingFunction:function(lhs, rhs)
00217 {
00218 if ([lhs queuePriority] < [rhs queuePriority])
00219 {
00220 return 1;
00221 }
00222 else
00223 {
00224 if ([lhs queuePriority] > [rhs queuePriority])
00225 {
00226 return -1;
00227 }
00228 else
00229 {
00230 return 0;
00231 }
00232 }
00233 }
00234 context:nil];
00235 }
00236 }
00237
00238 - (void)_runOpsSynchronously:(CPArray)ops
00239 {
00240 if (ops)
00241 {
00242 var keepGoing = YES;
00243 while (keepGoing)
00244 {
00245 var i = 0;
00246 keepGoing = NO;
00247
00248
00249 for (i = 0; i < [ops count]; i++)
00250 {
00251 var op = [ops objectAtIndex:i];
00252 if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
00253 {
00254 [op start];
00255 }
00256 }
00257
00258
00259 for (i = 0; i < [ops count]; i++)
00260 {
00261 var op = [ops objectAtIndex:i];
00262 if (![op isFinished] && ![op isCancelled])
00263 {
00264 keepGoing = YES;
00265 }
00266 }
00267 }
00268 }
00269 }
00270
00274 + (CPOperationQueue)mainQueue
00275 {
00276 if (!cpOperationMainQueue)
00277 {
00278 cpOperationMainQueue = [[CPOperationQueue alloc] init];
00279 [cpOperationMainQueue setName:@"main"];
00280 }
00281
00282 return cpOperationMainQueue;
00283 }
00284
00288 + (CPOperationQueue)currentQueue
00289 {
00290 return [CPOperationQueue mainQueue];
00291 }
00292
00293 @end