API 0.9.5
Foundation/CPOperationQueue.j
Go to the documentation of this file.
00001 /*
00002  * CPOperationQueue.j
00003  *
00004  * Created by Johannes Fahrenkrug.
00005  * Copyright 2009, Springenwerk.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 
00023 // the global queue (mainQueue)
00024 var cpOperationMainQueue = nil;
00025 
00030 @implementation CPOperationQueue : CPObject
00031 {
00032     CPArray _operations;
00033     BOOL _suspended;
00034     CPString _name;
00035     CPTimer _timer;
00036 }
00037 
00038 - (id)init
00039 {
00040     self = [super init];
00041 
00042     if (self)
00043     {
00044         _operations = [[CPArray alloc] init];
00045         _suspended = NO;
00046         _currentlyModifyingOps = NO;
00047         _timer = [CPTimer scheduledTimerWithTimeInterval:0.01
00048                                                   target:self
00049                                                 selector:@selector(_runNextOpsInQueue)
00050                                                 userInfo:nil
00051                                                  repeats:YES];
00052     }
00053     return self;
00054 }
00055 
00056 - (void)_runNextOpsInQueue
00057 {
00058     if (!_suspended && [self operationCount] > 0)
00059     {
00060         var i = 0,
00061             count = [_operations count];
00062 
00063         for (; i < 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             count = [_operations count];
00164 
00165         for (; i < count; i++)
00166         {
00167             [[_operations objectAtIndex:i] cancel];
00168         }
00169     }
00170 }
00171 
00175 - (void)waitUntilAllOperationsAreFinished
00176 {
00177     // lets first stop the timer so it won't interfere
00178     [self _enableTimer:NO];
00179     [self _runOpsSynchronously:_operations];
00180     if (!_suspended)
00181     {
00182         [self _enableTimer:YES];
00183     }
00184 }
00185 
00186 
00191 - (int)maxConcurrentOperationCount
00192 {
00193     return 1;
00194 }
00195 
00200 - (void)setSuspended:(BOOL)suspend
00201 {
00202     _suspended = suspend;
00203     [self _enableTimer:!suspend];
00204 }
00205 
00209 - (BOOL)isSuspended
00210 {
00211     return _suspended;
00212 }
00213 
00214 - (void)_sortOpsByPriority:(CPArray)someOps
00215 {
00216     if (someOps)
00217     {
00218         [someOps sortUsingFunction:function(lhs, rhs)
00219         {
00220             if ([lhs queuePriority] < [rhs queuePriority])
00221             {
00222                 return 1;
00223             }
00224             else
00225             {
00226                 if ([lhs queuePriority] > [rhs queuePriority])
00227                 {
00228                     return -1;
00229                 }
00230                 else
00231                 {
00232                     return 0;
00233                 }
00234             }
00235         }
00236         context:nil];
00237     }
00238 }
00239 
00240 - (void)_runOpsSynchronously:(CPArray)ops
00241 {
00242     if (ops)
00243     {
00244         var keepGoing = YES;
00245         while (keepGoing)
00246         {
00247             var i = 0,
00248                 count = [ops count];
00249 
00250             keepGoing = NO;
00251 
00252             // start the ones that are ready
00253             for (; i < count; i++)
00254             {
00255                 var op = [ops objectAtIndex:i];
00256                 if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
00257                 {
00258                     [op start];
00259                 }
00260             }
00261 
00262             // make sure they are all done
00263             for (i = 0; i < count; i++)
00264             {
00265                 var op = [ops objectAtIndex:i];
00266                 if (![op isFinished] && ![op isCancelled])
00267                 {
00268                     keepGoing = YES;
00269                 }
00270             }
00271         }
00272     }
00273 }
00274 
00278 + (CPOperationQueue)mainQueue
00279 {
00280     if (!cpOperationMainQueue)
00281     {
00282         cpOperationMainQueue = [[CPOperationQueue alloc] init];
00283         [cpOperationMainQueue setName:@"main"];
00284     }
00285 
00286     return cpOperationMainQueue;
00287 }
00288 
00292 + (CPOperationQueue)currentQueue
00293 {
00294     return [CPOperationQueue mainQueue];
00295 }
00296 
00297 @end
00298 
00299 @implementation CPOperationQueue (CPSynthesizedAccessors)
00300 
00304 - (CPString)name
00305 {
00306     return _name;
00307 }
00308 
00312 - (void)setName:(CPString)aValue
00313 {
00314     _name = aValue;
00315 }
00316 
00317 @end
 All Classes Files Functions Variables Defines