gecko-dev/xpcom/threads/nsITimer.idl

204 lines
7.7 KiB
Plaintext
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 11:12:37 +00:00
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIObserver;
interface nsIEventTarget;
%{C++
/**
* The signature of the timer callback function passed to initWithFuncCallback.
* This is the function that will get called when the timer expires if the
* timer is initialized via initWithFuncCallback.
*
* @param aTimer the timer which has expired
* @param aClosure opaque parameter passed to initWithFuncCallback
*/
class nsITimer;
typedef void (*nsTimerCallbackFunc) (nsITimer *aTimer, void *aClosure);
%}
native nsTimerCallbackFunc(nsTimerCallbackFunc);
/**
* The callback interface for timers.
*/
interface nsITimer;
[function, scriptable, uuid(a796816d-7d47-4348-9ab8-c7aeb3216a7d)]
interface nsITimerCallback : nsISupports
{
/**
* @param aTimer the timer which has expired
*/
void notify(in nsITimer timer);
};
%{C++
// Two timer deadlines must differ by less than half the PRIntervalTime domain.
#define DELAY_INTERVAL_LIMIT PR_BIT(8 * sizeof(PRIntervalTime) - 1)
%}
/**
* nsITimer instances must be initialized by calling one of the "init" methods
* documented below. You may also re-initialize (using one of the init()
* methods) an existing instance to avoid the overhead of destroying and
* creating a timer. It is not necessary to cancel the timer in that case.
*
* By default a timer will fire on the thread that created it. Set the .target
* attribute to fire on a different thread. Once you have set a timer's .target
* and called one of its init functions, any further interactions with the timer
* (calling cancel(), changing member fields, etc) should only be done by the
* target thread, or races may occur with bad results like timers firing after
* they've been canceled, and/or not firing after re-initiatization.
*/
[scriptable, uuid(193fc37a-8aa4-4d29-aa57-1acd87c26b66)]
interface nsITimer : nsISupports
{
/* Timer types */
/**
* Type of a timer that fires once only.
*/
const short TYPE_ONE_SHOT = 0;
/**
* After firing, a TYPE_REPEATING_SLACK timer is stopped and not restarted
* until its callback completes. Specified timer period will be at least
* the time between when processing for last firing the callback completes
* and when the next firing occurs.
*
* This is the preferable repeating type for most situations.
*/
const short TYPE_REPEATING_SLACK = 1;
/**
* An TYPE_REPEATING_PRECISE repeating timer aims to have constant period
* between firings. The processing time for each timer callback should not
* influence the timer period. However, if the processing for the last
* timer firing could not be completed until just before the next firing
* occurs, then you could have two timer notification routines being
Bug 650379. Add a new XPCOM timer type that is like TYPE_REPEATING_PRECISE but does not swamp the event queue if the callback takes longer than the timer interval to run. r=cjones, sr=brendan This implements proposal 3 from bug 650379 comment 13. The main difference between TYPE_REPEATING_PRECISE and TYPE_REPEATING_PRECISE_CAN_SKIP is to not AddTimer the REPEATING_PRECISE_CAN_SKIP timer until after the callback has run; this guarantees that no more timer events will be posted until after the callback finishes executing. A secondary change is to make REPEATING_PRECISE_CAN_SKIP timers advance their firing time to mDelay from when PostTimerEvent is called, not mDelay from the old mTimeout. While this arguably makes them less precise, the alternative is that if a timer is significantly delayed for some reason (e.g. because the user puts the computer to sleep for a while) it will then fire a whole bunch of times to "catch up" to where it's supposed to be, advancing its firing time by mDelay at a time. That seems undesirable. An alternate approach would have been to readd the timer from inside PostTimerEvent, but only if we're not in the middle of firing the timer. That would allow more precise timers in the case when the callback is not taking too long, but still handle gracefully the case when the callback is slow. Unfortunately this falls down if something _else_ is hogging the main thread event loop (e.g. some other timer has a slow callback, or whatever); in that case we would post multiple events for the one precise timer while the event-loop-hogging operation is running. So I don't think we should do that.
2011-04-28 23:33:52 +00:00
* executed in quick succession. Furthermore, if your callback processing
* time is longer than the timer period, then the timer will post more
* notifications while your callback is running. For example, if a
* REPEATING_PRECISE timer has a 10ms period and a callback takes 50ms,
* then by the time the callback is done there will be 5 events to run the
* timer callback in the event queue. Furthermore, the next scheduled time
* will always advance by exactly the delay every time the timer fires.
* This means that if the clock increments without the timer thread running
* (e.g. the computer is asleep) when the timer thread gets to run again it
* will post all the events that it "missed" while it wasn't running. Use
* this timer type with extreme caution. Chances are, this is not what you
* want.
*/
const short TYPE_REPEATING_PRECISE = 2;
Bug 650379. Add a new XPCOM timer type that is like TYPE_REPEATING_PRECISE but does not swamp the event queue if the callback takes longer than the timer interval to run. r=cjones, sr=brendan This implements proposal 3 from bug 650379 comment 13. The main difference between TYPE_REPEATING_PRECISE and TYPE_REPEATING_PRECISE_CAN_SKIP is to not AddTimer the REPEATING_PRECISE_CAN_SKIP timer until after the callback has run; this guarantees that no more timer events will be posted until after the callback finishes executing. A secondary change is to make REPEATING_PRECISE_CAN_SKIP timers advance their firing time to mDelay from when PostTimerEvent is called, not mDelay from the old mTimeout. While this arguably makes them less precise, the alternative is that if a timer is significantly delayed for some reason (e.g. because the user puts the computer to sleep for a while) it will then fire a whole bunch of times to "catch up" to where it's supposed to be, advancing its firing time by mDelay at a time. That seems undesirable. An alternate approach would have been to readd the timer from inside PostTimerEvent, but only if we're not in the middle of firing the timer. That would allow more precise timers in the case when the callback is not taking too long, but still handle gracefully the case when the callback is slow. Unfortunately this falls down if something _else_ is hogging the main thread event loop (e.g. some other timer has a slow callback, or whatever); in that case we would post multiple events for the one precise timer while the event-loop-hogging operation is running. So I don't think we should do that.
2011-04-28 23:33:52 +00:00
/**
* A TYPE_REPEATING_PRECISE_CAN_SKIP repeating timer aims to have constant
* period between firings. The processing time for each timer callback
* should not influence the timer period. However this timer type
* guarantees that it will not queue up new events to fire the callback
* until the previous callback event finishes firing. If the callback
* takes a long time, then the next callback will be scheduled immediately
* afterward, but only once, unlike TYPE_REPEATING_PRECISE. If you want a
* non-slack timer, you probably want this one.
*/
const short TYPE_REPEATING_PRECISE_CAN_SKIP = 3;
/**
* Initialize a timer that will fire after the said delay.
* A user must keep a reference to this timer till it is
* is no longer needed or has been cancelled.
*
* @param aObserver the callback object that observes the
* ``timer-callback'' topic with the subject being
* the timer itself when the timer fires:
*
* observe(nsISupports aSubject, => nsITimer
* string aTopic, => ``timer-callback''
* wstring data => null
*
* @param aDelay delay in milliseconds for timer to fire
* @param aType timer type per TYPE* consts defined above
*/
void init(in nsIObserver aObserver, in unsigned long aDelay,
in unsigned long aType);
/**
* Initialize a timer to fire after the given millisecond interval.
* This version takes a function to call and a closure to pass to
* that function.
*
* @param aFunc The function to invoke
* @param aClosure An opaque pointer to pass to that function
* @param aDelay The millisecond interval
* @param aType Timer type per TYPE* consts defined above
*/
[noscript] void initWithFuncCallback(in nsTimerCallbackFunc aCallback,
in voidPtr aClosure,
in unsigned long aDelay,
in unsigned long aType);
/**
* Initialize a timer to fire after the given millisecond interval.
* This version takes a function to call.
*
* @param aFunc nsITimerCallback interface to call when timer expires
* @param aDelay The millisecond interval
* @param aType Timer type per TYPE* consts defined above
*/
void initWithCallback(in nsITimerCallback aCallback,
in unsigned long aDelay,
in unsigned long aType);
/**
* Cancel the timer. This method works on all types, not just on repeating
* timers -- you might want to cancel a TYPE_ONE_SHOT timer, and even reuse
* it by re-initializing it (to avoid object destruction and creation costs
* by conserving one timer instance).
*/
void cancel();
/**
* The millisecond delay of the timeout.
*
* NOTE: Re-setting the delay on a one-shot timer that has already fired
* doesn't restart the timer. Call one of the init() methods to restart
* a one-shot timer.
*/
attribute unsigned long delay;
/**
* The timer type - one of the above TYPE_* constants.
*/
attribute unsigned long type;
/**
* The opaque pointer pass to initWithFuncCallback.
*/
[noscript] readonly attribute voidPtr closure;
/**
* The nsITimerCallback object passed to initWithCallback.
*/
readonly attribute nsITimerCallback callback;
/**
* The nsIEventTarget where the callback will be dispatched. Note that this
* target may only be set before the call to one of the init methods above.
*
* By default the target is the thread that created the timer.
*/
attribute nsIEventTarget target;
};
%{C++
#define NS_TIMER_CONTRACTID "@mozilla.org/timer;1"
#define NS_TIMER_CALLBACK_TOPIC "timer-callback"
%}