30 function _CPRunLoopPerformCompare(lhs, rhs)
32 return [rhs order] - [lhs order];
35 var _CPRunLoopPerformPool = [],
36 _CPRunLoopPerformPoolCapacity = 5;
39 @implementation _CPRunLoopPerform :
CPObject
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;
157 int _runLoopInsuranceTimer;
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 = {};
271 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
273 if (!_runLoopInsuranceTimer)
274 _runLoopInsuranceTimer = window.setNativeTimeout(
function()
293 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
295 if (_runLoopInsuranceTimer)
297 window.clearNativeTimeout(_runLoopInsuranceTimer);
298 _runLoopInsuranceTimer = nil;
304 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;
328 var timer = timers[index];
335 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
340 timer._lastNativeRunLoopsForModes[aMode] = 0;
342 timers.splice(index, 1);
349 var newTimers = _timersForModes[aMode];
351 if (newTimers && newTimers.length)
353 index = newTimers.length;
357 var timer = newTimers[index];
360 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
362 newTimers.splice(index, 1);
365 _timersForModes[aMode] = newTimers.concat(timers);
368 _timersForModes[aMode] = timers;
370 _nextTimerFireDatesForModes[aMode] = nextFireDate;
373 if (_nextTimerFireDatesForModes[aMode] !== nil)
374 _nativeTimersForModes[aMode] = window.setNativeTimeout(
function()
376 _effectiveDate = nextFireDate;
377 _nativeTimersForModes[aMode] = nil;
380 _effectiveDate = nil;
381 }, MAX(0, [nextFireDate timeIntervalSinceNow] * 1000));
385 var performs = _orderedPerforms,
386 index = performs.length;
388 _orderedPerforms = [];
392 var perform = performs[index];
396 [_CPRunLoopPerform _poolPerform:perform];
398 performs.splice(index, 1);
402 if (_orderedPerforms.length)
404 _orderedPerforms = _orderedPerforms.concat(performs);
405 _orderedPerforms.sort(_CPRunLoopPerformCompare);
408 _orderedPerforms = performs;