API  0.9.10
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 
29 @implementation CPOperationQueue : CPObject
30 {
31  CPArray _operations;
32  BOOL _suspended;
33  CPString _name;
34  CPTimer _timer;
35 }
36 
37 - (id)init
38 {
39  self = [super init];
40 
41  if (self)
42  {
43  _operations = [[CPArray alloc] init];
44  _suspended = NO;
45 // _currentlyModifyingOps = NO;
47  target:self
48  selector:@selector(_runNextOpsInQueue)
49  userInfo:nil
50  repeats:YES];
51  }
52  return self;
53 }
54 
55 - (void)_runNextOpsInQueue
56 {
57  if (!_suspended && [self operationCount] > 0)
58  {
59  var i = 0,
60  count = [_operations count];
61 
62  for (; i < count; i++)
63  {
64  var op = [_operations objectAtIndex:i];
65  if ([op isReady] && ![op isFinished] && ![op isExecuting])
66  {
67  [op start];
68  }
69  }
70  }
71 }
72 
73 - (void)_enableTimer:(BOOL)enable
74 {
75  if (!enable)
76  {
77  if (_timer)
78  {
79  [_timer invalidate];
80  _timer = nil;
81  }
82  }
83  else
84  {
85  if (!_timer)
86  {
88  target:self
89  selector:@selector(_runNextOpsInQueue)
90  userInfo:nil
91  repeats:YES];
92  }
93  }
94 }
95 
100 - (void)addOperation:(CPOperation)anOperation
101 {
102  [self willChangeValueForKey:@"operations"];
103  [self willChangeValueForKey:@"operationCount"];
104  [_operations addObject:anOperation];
105  [self _sortOpsByPriority:_operations];
106  [self didChangeValueForKey:@"operations"];
107  [self didChangeValueForKey:@"operationCount"];
108 }
109 
115 - (void)addOperations:(CPArray)ops waitUntilFinished:(BOOL)wait
116 {
117  if (ops)
118  {
119  if (wait)
120  {
121  [self _sortOpsByPriority:ops];
122  [self _runOpsSynchronously:ops];
123  }
124 
125  [_operations addObjectsFromArray:ops];
126  [self _sortOpsByPriority:_operations];
127  }
128 }
129 
134 - (void)addOperationWithFunction:(JSObject)aFunction
135 {
137 }
138 
139 - (CPArray)operations
140 {
141  return _operations;
142 }
143 
145 {
146  if (_operations)
147  {
148  return [_operations count];
149  }
150 
151  return 0;
152 }
153 
158 {
159  if (_operations)
160  {
161  var i = 0,
162  count = [_operations count];
163 
164  for (; i < count; i++)
165  {
166  [[_operations objectAtIndex:i] cancel];
167  }
168  }
169 }
170 
175 {
176  // lets first stop the timer so it won't interfere
177  [self _enableTimer:NO];
178  [self _runOpsSynchronously:_operations];
179  if (!_suspended)
180  {
181  [self _enableTimer:YES];
182  }
183 }
184 
185 
191 {
192  return 1;
193 }
194 
199 - (void)setSuspended:(BOOL)suspend
200 {
201  _suspended = suspend;
202  [self _enableTimer:!suspend];
203 }
204 
208 - (BOOL)isSuspended
209 {
210  return _suspended;
211 }
212 
213 - (void)_sortOpsByPriority:(CPArray)someOps
214 {
215  if (someOps)
216  {
217  [someOps sortUsingFunction:function(lhs, rhs)
218  {
219  if ([lhs queuePriority] < [rhs queuePriority])
220  {
221  return 1;
222  }
223  else
224  {
225  if ([lhs queuePriority] > [rhs queuePriority])
226  {
227  return -1;
228  }
229  else
230  {
231  return 0;
232  }
233  }
234  }
235  context:nil];
236  }
237 }
238 
239 - (void)_runOpsSynchronously:(CPArray)ops
240 {
241  if (ops)
242  {
243  var keepGoing = YES;
244  while (keepGoing)
245  {
246  var i = 0,
247  count = [ops count];
248 
249  keepGoing = NO;
250 
251  // start the ones that are ready
252  for (; i < count; i++)
253  {
254  var op = [ops objectAtIndex:i];
255  if ([op isReady] && ![op isFinished] && ![op isExecuting])
256  {
257  [op start];
258  }
259  }
260 
261  // make sure they are all done
262  for (i = 0; i < count; i++)
263  {
264  var op = [ops objectAtIndex:i];
265  if (![op isFinished] && ![op isCancelled])
266  {
267  keepGoing = YES;
268  }
269  }
270  }
271  }
272 }
273 
278 {
280  {
282  [cpOperationMainQueue setName:@"main"];
283  }
284 
285  return cpOperationMainQueue;
286 }
287 
292 {
293  return [CPOperationQueue mainQueue];
294 }
295 
296 @end
297 
299 
304 {
305  return _name;
306 }
307 
311 - (void)setName:(CPString)aValue
312 {
313  _name = aValue;
314 }
315 
316 @end
void willChangeValueForKey:(CPString aKey)
An immutable string (collection of characters).
Definition: CPString.h:2
Represents an operation using a JavaScript function that can be run in an CPOperationQueue.
var cpOperationMainQueue
void addOperation:(CPOperation anOperation)
CPOperationQueue mainQueue()
void waitUntilAllOperationsAreFinished()
void didChangeValueForKey:(CPString aKey)
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
Represents an operation that can be run in an CPOperationQueue.
Definition: CPOperation.h:2
id init()
Definition: CPObject.j:145
id functionOperationWithFunction:(JSObject jsFunction)
CPOperationQueue currentQueue()
id alloc()
Definition: CPObject.j:130
Represents an operation queue that can run CPOperations.