30 function _CPRunLoopPerformCompare(lhs, rhs)
32 return [rhs order] - [lhs order];
35 var _CPRunLoopPerformPool = [],
36 _CPRunLoopPerformPoolCapacity = 5;
39 @implementation _CPRunLoopPerform :
CPObject
45 CPArray _runLoopModes;
49 + (void)_poolPerform:(_CPRunLoopPerform)aPerform
51 if (!aPerform || _CPRunLoopPerformPool.length >= _CPRunLoopPerformPoolCapacity)
54 _CPRunLoopPerformPool.push(aPerform);
57 + (_CPRunLoopPerform)performWithSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
59 if (_CPRunLoopPerformPool.length)
61 var perform = _CPRunLoopPerformPool.pop();
63 perform._target = aTarget;
64 perform._selector = aSelector;
65 perform._argument = anArgument;
66 perform._order = anOrder;
67 perform._runLoopModes = modes;
68 perform._isValid = YES;
73 return [[
self alloc] initWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes];
76 - (id)initWithSelector:(
SEL)aSelector target:(
SEL)aTarget argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
82 _selector = aSelector;
84 _argument = anArgument;
86 _runLoopModes = modes;
113 - (BOOL)fireInMode:(
CPString)aRunLoopMode
118 if ([_runLoopModes containsObject:aRunLoopMode])
120 [_target performSelector:_selector withObject:_argument];
150 Object _timersForModes;
151 Object _nativeTimersForModes;
152 CPDate _nextTimerFireDatesForModes;
156 CPArray _orderedPerforms;
157 int _runLoopInsuranceTimer;
168 CPMainRunLoop = [[
CPRunLoop alloc] init];
177 _orderedPerforms = [];
179 _timersForModes = {};
180 _nativeTimersForModes = {};
181 _nextTimerFireDatesForModes = {};
192 return CPMainRunLoop;
200 return CPMainRunLoop;
211 - (void)performSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument order:(
int)anOrder modes:(CPArray)modes
213 var perform = [_CPRunLoopPerform performWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes],
214 count = _orderedPerforms.length;
218 if (anOrder < [_orderedPerforms[count] order])
221 _orderedPerforms.splice(count + 1, 0, perform);
230 - (void)cancelPerformSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument
232 var count = _orderedPerforms.length;
236 var perform = _orderedPerforms[count];
238 if ([perform selector] === aSelector && [perform target] == aTarget && [perform argument] == anArgument)
239 [_orderedPerforms[count] invalidate];
246 - (void)performSelectors
257 if (_timersForModes[aMode])
258 _timersForModes[aMode].push(aTimer);
260 _timersForModes[aMode] = [aTimer];
264 if (!aTimer._lastNativeRunLoopsForModes)
265 aTimer._lastNativeRunLoopsForModes = {};
270 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
272 if (!_runLoopInsuranceTimer)
273 _runLoopInsuranceTimer = window.setNativeTimeout(
function()
292 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
294 if (_runLoopInsuranceTimer)
296 window.clearNativeTimeout(_runLoopInsuranceTimer);
297 _runLoopInsuranceTimer = nil;
303 nextTimerFireDate = _nextTimerFireDatesForModes[aMode];
307 if (_didAddTimer || nextTimerFireDate && nextTimerFireDate <= now)
312 if (_nativeTimersForModes[aMode] !== nil)
314 window.clearNativeTimeout(_nativeTimersForModes[aMode]);
316 _nativeTimersForModes[aMode] = nil;
320 var timers = _timersForModes[aMode],
321 index = timers.length;
323 _timersForModes[aMode] = nil;
327 var hasNativeTimers = [CFBundle.environments() indexOfObject:("Browser")] !==
CPNotFound;
332 var timer = timers[index];
334 if ((!hasNativeTimers || timer._lastNativeRunLoopsForModes[aMode] <
CPRunLoopLastNativeRunLoop) && timer._isValid && timer._fireDate <= now)
339 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
344 timer._lastNativeRunLoopsForModes[aMode] = 0;
346 timers.splice(index, 1);
353 var newTimers = _timersForModes[aMode];
355 if (newTimers && newTimers.length)
357 index = newTimers.length;
361 var timer = newTimers[index];
364 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
366 newTimers.splice(index, 1);
369 _timersForModes[aMode] = newTimers.concat(timers);
372 _timersForModes[aMode] = timers;
374 _nextTimerFireDatesForModes[aMode] = nextFireDate;
377 if (_nextTimerFireDatesForModes[aMode] !== nil)
378 _nativeTimersForModes[aMode] = window.setNativeTimeout(
function()
380 _effectiveDate = nextFireDate;
381 _nativeTimersForModes[aMode] = nil;
384 _effectiveDate = nil;
385 }, MAX(0, [nextFireDate timeIntervalSinceNow] * 1000));
389 var performs = _orderedPerforms,
390 index = performs.length;
392 _orderedPerforms = [];
396 var perform = performs[index];
400 [_CPRunLoopPerform _poolPerform:perform];
402 performs.splice(index, 1);
406 if (_orderedPerforms.length)
408 _orderedPerforms = _orderedPerforms.concat(performs);
409 _orderedPerforms.sort(_CPRunLoopPerformCompare);
412 _orderedPerforms = performs;