API  0.9.6
 All Classes Files Functions Variables Macros Groups Pages
CPOperationQueue.j
Go to the documentation of this file.
1 /*
2  * CPOperationQueue.j
3  *
4  * Created by Johannes Fahrenkrug.
5  * Copyright 2009, Springenwerk.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 
23 // the global queue (mainQueue)
25 
30 @implementation CPOperationQueue : CPObject
31 {
32  CPArray _operations;
33  BOOL _suspended;
34  CPString _name;
35  CPTimer _timer;
36 }
37 
38 - (id)init
39 {
40  self = [super init];
41 
42  if (self)
43  {
44  _operations = [[CPArray alloc] init];
45  _suspended = NO;
46  _currentlyModifyingOps = NO;
48  target:self
49  selector:@selector(_runNextOpsInQueue)
50  userInfo:nil
51  repeats:YES];
52  }
53  return self;
54 }
55 
56 - (void)_runNextOpsInQueue
57 {
58  if (!_suspended && [self operationCount] > 0)
59  {
60  var i = 0,
61  count = [_operations count];
62 
63  for (; i < count; i++)
64  {
65  var op = [_operations objectAtIndex:i];
66  if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
67  {
68  [op start];
69  }
70  }
71  }
72 }
73 
74 - (void)_enableTimer:(BOOL)enable
75 {
76  if (!enable)
77  {
78  if (_timer)
79  {
80  [_timer invalidate];
81  _timer = nil;
82  }
83  }
84  else
85  {
86  if (!_timer)
87  {
89  target:self
90  selector:@selector(_runNextOpsInQueue)
91  userInfo:nil
92  repeats:YES];
93  }
94  }
95 }
96 
101 - (void)addOperation:(CPOperation)anOperation
102 {
103  [self willChangeValueForKey:@"operations"];
104  [self willChangeValueForKey:@"operationCount"];
105  [_operations addObject:anOperation];
106  [self _sortOpsByPriority:_operations];
107  [self didChangeValueForKey:@"operations"];
108  [self didChangeValueForKey:@"operationCount"];
109 }
110 
116 - (void)addOperations:(CPArray)ops waitUntilFinished:(BOOL)wait
117 {
118  if (ops)
119  {
120  if (wait)
121  {
122  [self _sortOpsByPriority:ops];
123  [self _runOpsSynchronously:ops];
124  }
125 
126  [_operations addObjectsFromArray:ops];
127  [self _sortOpsByPriority:_operations];
128  }
129 }
130 
135 - (void)addOperationWithFunction:(JSObject)aFunction
136 {
138 }
139 
140 - (CPArray)operations
141 {
142  return _operations;
143 }
144 
145 - (int)operationCount
146 {
147  if (_operations)
148  {
149  return [_operations count];
150  }
151 
152  return 0;
153 }
154 
158 - (void)cancelAllOperations
159 {
160  if (_operations)
161  {
162  var i = 0,
163  count = [_operations count];
164 
165  for (; i < count; i++)
166  {
167  [[_operations objectAtIndex:i] cancel];
168  }
169  }
170 }
171 
175 - (void)waitUntilAllOperationsAreFinished
176 {
177  // lets first stop the timer so it won't interfere
178  [self _enableTimer:NO];
179  [self _runOpsSynchronously:_operations];
180  if (!_suspended)
181  {
182  [self _enableTimer:YES];
183  }
184 }
185 
186 
191 - (int)maxConcurrentOperationCount
192 {
193  return 1;
194 }
195 
200 - (void)setSuspended:(BOOL)suspend
201 {
202  _suspended = suspend;
203  [self _enableTimer:!suspend];
204 }
205 
209 - (BOOL)isSuspended
210 {
211  return _suspended;
212 }
213 
214 - (void)_sortOpsByPriority:(CPArray)someOps
215 {
216  if (someOps)
217  {
218  [someOps sortUsingFunction:function(lhs, rhs)
219  {
220  if ([lhs queuePriority] < [rhs queuePriority])
221  {
222  return 1;
223  }
224  else
225  {
226  if ([lhs queuePriority] > [rhs queuePriority])
227  {
228  return -1;
229  }
230  else
231  {
232  return 0;
233  }
234  }
235  }
236  context:nil];
237  }
238 }
239 
240 - (void)_runOpsSynchronously:(CPArray)ops
241 {
242  if (ops)
243  {
244  var keepGoing = YES;
245  while (keepGoing)
246  {
247  var i = 0,
248  count = [ops count];
249 
250  keepGoing = NO;
251 
252  // start the ones that are ready
253  for (; i < count; i++)
254  {
255  var op = [ops objectAtIndex:i];
256  if ([op isReady] && ![op isCancelled] && ![op isFinished] && ![op isExecuting])
257  {
258  [op start];
259  }
260  }
261 
262  // make sure they are all done
263  for (i = 0; i < count; i++)
264  {
265  var op = [ops objectAtIndex:i];
266  if (![op isFinished] && ![op isCancelled])
267  {
268  keepGoing = YES;
269  }
270  }
271  }
272  }
273 }
274 
278 + (CPOperationQueue)mainQueue
279 {
281  {
283  [cpOperationMainQueue setName:@"main"];
284  }
285 
286  return cpOperationMainQueue;
287 }
288 
292 + (CPOperationQueue)currentQueue
293 {
294  return [CPOperationQueue mainQueue];
295 }
296 
297 @end
298 
300 
304 - (CPString)name
305 {
306  return _name;
307 }
308 
312 - (void)setName:(CPString)aValue
313 {
314  _name = aValue;
315 }
316 
317 @end