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];
149 Object _timersForModes;
150 Object _nativeTimersForModes;
151 CPDate _nextTimerFireDatesForModes;
155 CPArray _orderedPerforms;
156 int _runLoopInsuranceTimer;
176 _orderedPerforms = [];
178 _timersForModes = {};
179 _nativeTimersForModes = {};
180 _nextTimerFireDatesForModes = {};
191 return CPMainRunLoop;
199 return CPMainRunLoop;
210 - (void)performSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument order:(
int)anOrder modes:(CPArray)modes
212 var perform = [_CPRunLoopPerform performWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes],
213 count = _orderedPerforms.length;
217 if (anOrder < [_orderedPerforms[count] order])
220 _orderedPerforms.splice(count + 1, 0, perform);
229 - (void)cancelPerformSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument
231 var count = _orderedPerforms.length;
235 var perform = _orderedPerforms[count];
237 if ([perform selector] === aSelector && [perform target] == aTarget && [perform argument] == anArgument)
238 [_orderedPerforms[count] invalidate];
245 - (void)performSelectors
256 if (_timersForModes[aMode])
257 _timersForModes[aMode].push(aTimer);
259 _timersForModes[aMode] = [aTimer];
263 if (!aTimer._lastNativeRunLoopsForModes)
264 aTimer._lastNativeRunLoopsForModes = {};
269 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
271 if (!_runLoopInsuranceTimer)
272 _runLoopInsuranceTimer = window.setNativeTimeout(
function()
291 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
293 if (_runLoopInsuranceTimer)
295 window.clearNativeTimeout(_runLoopInsuranceTimer);
296 _runLoopInsuranceTimer = nil;
302 nextTimerFireDate = _nextTimerFireDatesForModes[aMode];
306 if (_didAddTimer || nextTimerFireDate && nextTimerFireDate <= now)
311 if (_nativeTimersForModes[aMode] !== nil)
313 window.clearNativeTimeout(_nativeTimersForModes[aMode]);
315 _nativeTimersForModes[aMode] = nil;
319 var timers = _timersForModes[aMode],
320 index = timers.length;
322 _timersForModes[aMode] = nil;
326 var hasNativeTimers = [CFBundle.environments() indexOfObject:("Browser")] !==
CPNotFound;
331 var timer = timers[index];
333 if ((!hasNativeTimers || timer._lastNativeRunLoopsForModes[aMode] <
CPRunLoopLastNativeRunLoop) && timer._isValid && timer._fireDate <= now)
338 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
343 timer._lastNativeRunLoopsForModes[aMode] = 0;
345 timers.splice(index, 1);
352 var newTimers = _timersForModes[aMode];
354 if (newTimers && newTimers.length)
356 index = newTimers.length;
360 var timer = newTimers[index];
363 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
365 newTimers.splice(index, 1);
368 _timersForModes[aMode] = newTimers.concat(timers);
371 _timersForModes[aMode] = timers;
373 _nextTimerFireDatesForModes[aMode] = nextFireDate;
376 if (_nextTimerFireDatesForModes[aMode] !== nil)
377 _nativeTimersForModes[aMode] = window.setNativeTimeout(
function()
379 _effectiveDate = nextFireDate;
380 _nativeTimersForModes[aMode] = nil;
383 _effectiveDate = nil;
384 }, MAX(0, [nextFireDate timeIntervalSinceNow] * 1000));
388 var performs = _orderedPerforms,
389 index = performs.length;
391 _orderedPerforms = [];
395 var perform = performs[index];
399 [_CPRunLoopPerform _poolPerform:perform];
401 performs.splice(index, 1);
405 if (_orderedPerforms.length)
407 _orderedPerforms = _orderedPerforms.concat(performs);
408 _orderedPerforms.sort(_CPRunLoopPerformCompare);
411 _orderedPerforms = performs;