30 function _CPRunLoopPerformCompare(lhs, rhs)
32 return [rhs order] - [lhs order];
35 var _CPRunLoopPerformPool = [],
36 _CPRunLoopPerformPoolCapacity = 5;
39 @implementation _CPRunLoopPerform :
CPObject 46 CPArray _runLoopModes;
50 + (void)_poolPerform:(_CPRunLoopPerform)aPerform
52 if (!aPerform || _CPRunLoopPerformPool.length >= _CPRunLoopPerformPoolCapacity)
55 _CPRunLoopPerformPool.push(aPerform);
58 + (_CPRunLoopPerform)performWithSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
60 if (_CPRunLoopPerformPool.length)
62 var perform = _CPRunLoopPerformPool.pop();
65 perform._target = aTarget;
66 perform._selector = aSelector;
67 perform._argument = anArgument;
68 perform._order = anOrder;
69 perform._runLoopModes = modes;
70 perform._isValid = YES;
75 return [[
self alloc] initWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes];
78 + (_CPRunLoopPerform)performWithBlock:(Function)aBlock argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
80 if (_CPRunLoopPerformPool.length)
82 var perform = _CPRunLoopPerformPool.pop();
84 perform._target = nil;
85 perform._selector = nil;
86 perform._block = aBlock;
87 perform._argument = anArgument;
88 perform._order = anOrder;
89 perform._runLoopModes = modes;
90 perform._isValid = YES;
95 return [[
self alloc] initWithBlock:aBlock argument:anArgument order:anOrder modes:modes];
98 - (id)initWithSelector:(
SEL)aSelector target:(
SEL)aTarget argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
104 _selector = aSelector;
106 _argument = anArgument;
108 _runLoopModes = modes;
115 - (id)initWithBlock:(Function)aBlock argument:(
id)anArgument order:(
unsigned)anOrder modes:(CPArray)modes
122 _argument = anArgument;
124 _runLoopModes = modes;
151 - (BOOL)fireInMode:(
CPString)aRunLoopMode
156 if ([_runLoopModes containsObject:aRunLoopMode])
161 [_target performSelector:_selector withObject:_argument];
190 Object _timersForModes;
191 Object _nativeTimersForModes;
192 CPDate _nextTimerFireDatesForModes;
196 CPArray _orderedPerforms;
197 int _runLoopInsuranceTimer;
218 _orderedPerforms = [];
220 _timersForModes = {};
221 _nativeTimersForModes = {};
222 _nextTimerFireDatesForModes = {};
234 return CPMainRunLoop;
242 return CPMainRunLoop;
253 - (void)performSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument order:(
int)anOrder modes:(CPArray)modes
255 var perform = [_CPRunLoopPerform performWithSelector:aSelector target:aTarget argument:anArgument order:anOrder modes:modes],
256 count = _orderedPerforms.length;
260 if (anOrder < [_orderedPerforms[count] order])
263 _orderedPerforms.splice(count + 1, 0, perform);
270 - (void)performBlock:(Function)aBlock argument:(
id)anArgument order:(
int)anOrder modes:(CPArray)modes
272 var perform = [_CPRunLoopPerform performWithBlock:aBlock argument:anArgument order:anOrder modes:modes],
273 count = _orderedPerforms.length;
277 if (anOrder < [_orderedPerforms[count] order])
280 _orderedPerforms.splice(count + 1, 0, perform);
289 - (void)cancelPerformSelector:(
SEL)aSelector target:(
id)aTarget argument:(
id)anArgument
291 var count = _orderedPerforms.length;
295 var perform = _orderedPerforms[count];
297 if ([perform selector] === aSelector && [perform target] == aTarget && [perform argument] == anArgument)
298 [_orderedPerforms[count] invalidate];
305 - (void)performSelectors
316 if (_timersForModes[aMode])
317 _timersForModes[aMode].push(aTimer);
319 _timersForModes[aMode] = [aTimer];
323 if (!aTimer._lastNativeRunLoopsForModes)
324 aTimer._lastNativeRunLoopsForModes = {};
329 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
331 if (!_runLoopInsuranceTimer)
332 _runLoopInsuranceTimer = window.setNativeTimeout(
function()
351 if ([CFBundle.environments() indexOfObject:(
"Browser")] !==
CPNotFound)
353 if (_runLoopInsuranceTimer)
355 window.clearNativeTimeout(_runLoopInsuranceTimer);
356 _runLoopInsuranceTimer = nil;
362 nextTimerFireDate = _nextTimerFireDatesForModes[aMode];
366 if (_didAddTimer || nextTimerFireDate && nextTimerFireDate <= now)
371 if (_nativeTimersForModes[aMode] !== nil)
373 window.clearNativeTimeout(_nativeTimersForModes[aMode]);
375 _nativeTimersForModes[aMode] = nil;
379 var timers = _timersForModes[aMode],
380 index = timers.length;
382 _timersForModes[aMode] = nil;
386 var hasNativeTimers = [CFBundle.environments() indexOfObject:("Browser")] !==
CPNotFound;
391 var timer = timers[index];
393 if ((!hasNativeTimers || timer._lastNativeRunLoopsForModes[aMode] <
CPRunLoopLastNativeRunLoop) && timer._isValid && timer._fireDate <= now)
398 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
403 timer._lastNativeRunLoopsForModes[aMode] = 0;
405 timers.splice(index, 1);
412 var newTimers = _timersForModes[aMode];
414 if (newTimers && newTimers.length)
416 index = newTimers.length;
420 var timer = newTimers[index];
423 nextFireDate = (nextFireDate === nil) ? timer._fireDate : [nextFireDate earlierDate:timer._fireDate];
425 newTimers.splice(index, 1);
428 _timersForModes[aMode] = newTimers.concat(timers);
431 _timersForModes[aMode] = timers;
433 _nextTimerFireDatesForModes[aMode] = nextFireDate;
436 if (_nextTimerFireDatesForModes[aMode] !== nil)
437 _nativeTimersForModes[aMode] = window.setNativeTimeout(
function()
439 _effectiveDate = nextFireDate;
440 _nativeTimersForModes[aMode] = nil;
443 _effectiveDate = nil;
444 }, MAX(0, [nextFireDate timeIntervalSinceNow] * 1000));
448 var performs = _orderedPerforms,
449 index = performs.length;
451 _orderedPerforms = [];
455 var perform = performs[index];
459 [_CPRunLoopPerform _poolPerform:perform];
461 performs.splice(index, 1);
465 if (_orderedPerforms.length)
467 _orderedPerforms = _orderedPerforms.concat(performs);
468 _orderedPerforms.sort(_CPRunLoopPerformCompare);
471 _orderedPerforms = performs;
475 var count = _observers.length;
478 var obs = _observers[count];
482 _observers.splice(count, 1);
495 this.activities = activities;
496 this.repeats = repeats;
498 this.callout = callout;
499 this.context = context;
511 var observers = runloop._observers;
514 observers = (runloop._observers = []);
516 if (observers.indexOf(observer) == -1)
517 observers.push(observer);
527 var observers = runloop._observers;
530 var idx = observers.indexOf(observer);
533 observers.splice(idx, 1);
535 if (observers.length == 0)
536 runloop._observers = nil;
var CPRunLoopLastNativeRunLoop
function CFRunLoopAddObserver(runloop, observer, mode)
function CFRunLoopObserverInvalidate(runloop, observer, mode)
A representation of a single point in time.
The main run loop for the application.
function CFRunLoopObserver(activities, repeats, order, callout, context)
function CFRunLoopRemoveObserver(runloop, observer, mode)
An immutable string (collection of characters).
CPDate limitDateForMode:(CPString aMode)
A timer object that can send a message after the given time interval.
CompletionHandlerAgent prototype invalidate
function CFRunLoopObserverCreate(activities, repeats, order, callout, context)