xpcom/threads/nsITimer.idl
author Henri Sivonen <hsivonen@hsivonen.fi>
Fri, 06 Jul 2018 10:44:43 +0300
changeset 489140 4ef0f163fdeb9afeddd87b37bfd987298c038542
parent 439793 1e1fbe9a79c6e59cb31ff0a08cdf9a5c04f1c5d3
child 528463 370bb868f97c912575e9b9d2987c3b6ce9a8135b
permissions -rw-r--r--
Bug 1402247 - Use encoding_rs for XPCOM string encoding conversions. r=Nika,erahm,froydnj. Correctness improvements: * UTF errors are handled safely per spec instead of dangerously truncating strings. * There are fewer converter implementations. Performance improvements: * The old code did exact buffer length math, which meant doing UTF math twice on each input string (once for length calculation and another time for conversion). Exact length math is more complicated when handling errors properly, which the old code didn't do. The new code does UTF math on the string content only once (when converting) but risks allocating more than once. There are heuristics in place to lower the probability of reallocation in cases where the double math avoidance isn't enough of a saving to absorb an allocation and memcpy. * Previously, in UTF-16 <-> UTF-8 conversions, an ASCII prefix was optimized but a single non-ASCII code point pessimized the rest of the string. The new code tries to get back on the fast ASCII path. * UTF-16 to Latin1 conversion guarantees less about handling of out-of-range input to eliminate an operation from the inner loop on x86/x86_64. * When assigning to a pre-existing string, the new code tries to reuse the old buffer instead of first releasing the old buffer and then allocating a new one. * When reallocating from the new code, the memcpy covers only the data that is part of the logical length of the old string instead of memcpying the whole capacity. (For old callers old excess memcpy behavior is preserved due to bogus callers. See bug 1472113.) * UTF-8 strings in XPConnect that are in the Latin1 range are passed to SpiderMonkey as Latin1. New features: * Conversion between UTF-8 and Latin1 is added in order to enable faster future interop between Rust code (or otherwise UTF-8-using code) and text node and SpiderMonkey code that uses Latin1. MozReview-Commit-ID: JaJuExfILM9

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * 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++
#include "mozilla/MemoryReporting.h"
#include "mozilla/TimeStamp.h"

/**
 * 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);

/**
 * The signature of the timer name callback function passed to
 * initWithNameableFuncCallback.
 * This is the function that will get called when timer profiling is enabled
 * via the "TimerFirings" log module.
 *
 * @param aTimer the timer which has expired
 * @param aAnonymize whether the name should avoid including privacy sensitive info
 * @param aClosure opaque parameter passed to initWithFuncCallback
 * @param aBuf a buffer in which to put the name
 * @param aLen the length of the buffer
 */
typedef void (*nsTimerNameCallbackFunc) (nsITimer *aTimer,
                                         bool aAnonymize,
                                         void *aClosure,
                                         char *aBuf, size_t aLen);
%}

native nsTimerCallbackFunc(nsTimerCallbackFunc);
native nsTimerNameCallbackFunc(nsTimerNameCallbackFunc);
[ref] native TimeDuration(mozilla::TimeDuration);

/**
 * 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(3de4b105-363c-482c-a409-baac83a01bfc)]
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;

  /**
   * TYPE_REPEATING_PRECISE is just a synonym for
   * TYPE_REPEATING_PRECISE_CAN_SKIP. They used to be distinct, but the old
   * TYPE_REPEATING_PRECISE kind was similar to TYPE_REPEATING_PRECISE_CAN_SKIP
   * while also being less useful. So the distinction was removed.
   */
  const short TYPE_REPEATING_PRECISE = 2;

  /**
   * 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.  This is the only non-slack timer available.
   */
  const short TYPE_REPEATING_PRECISE_CAN_SKIP = 3;

  /**
   * Same as TYPE_REPEATING_SLACK with the exception that idle events
   * won't yield to timers with this type.  Use this when you want an
   * idle callback to be scheduled to run even though this timer is
   * about to fire.
   */
  const short TYPE_REPEATING_SLACK_LOW_PRIORITY = 4;

  /**
   * Same as TYPE_ONE_SHOT with the exception that idle events won't
   * yield to timers with this type.  Use this when you want an idle
   * callback to be scheduled to run even though this timer is about
   * to fire.
   */
  const short TYPE_ONE_SHOT_LOW_PRIORITY = 5;

  /**
   * 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 callback object.
   *
   * @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);

  /**
   * Initialize a timer to fire after the high resolution TimeDuration.
   * This version takes a callback object.
   *
   * @param aFunc      nsITimerCallback interface to call when timer expires
   * @param aDelay     The high resolution interval
   * @param aType      Timer type per TYPE* consts defined above
   */
  [noscript] void InitHighResolutionWithCallback(in nsITimerCallback aCallback,
                                                 [const] in TimeDuration 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();

  /**
   * Like initWithFuncCallback, but also takes a name for the timer; the name
   * will be used when timer profiling is enabled via the "TimerFirings" log
   * module.
   *
   * @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
   * @param aName      The timer's name
   */
  [noscript] void initWithNamedFuncCallback(in nsTimerCallbackFunc aCallback,
                                            in voidPtr aClosure,
                                            in unsigned long aDelay,
                                            in unsigned long aType,
                                            in string aName);

  /**
   * Like initWithNamedFuncCallback, but instead of a timer name it takes a
   * callback that will provide a name when the timer fires.
   *
   * @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
   * @param aNameCallback  The callback function
   */
  [noscript] void initWithNameableFuncCallback(
                    in nsTimerCallbackFunc aCallback,
                    in voidPtr aClosure,
                    in unsigned long aDelay,
                    in unsigned long aType,
                    in nsTimerNameCallbackFunc aNameCallback);

  /**
   * 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;

  /**
   * The number of microseconds this nsITimer implementation can possibly
   * fire early.
   */
  [noscript] readonly attribute unsigned long allowedEarlyFiringMicroseconds;

%{C++
  virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
%}
};

%{C++
#include "nsCOMPtr.h"

already_AddRefed<nsITimer> NS_NewTimer();

already_AddRefed<nsITimer> NS_NewTimer(nsIEventTarget* aTarget);

nsresult
NS_NewTimerWithObserver(nsITimer** aTimer,
                        nsIObserver* aObserver,
                        uint32_t aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);
mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
NS_NewTimerWithObserver(nsIObserver* aObserver,
                        uint32_t aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);

nsresult
NS_NewTimerWithCallback(nsITimer** aTimer,
                        nsITimerCallback* aCallback,
                        uint32_t aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);
mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
NS_NewTimerWithCallback(nsITimerCallback* aCallback,
                        uint32_t aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);

nsresult
NS_NewTimerWithCallback(nsITimer** aTimer,
                        nsITimerCallback* aCallback,
                        const mozilla::TimeDuration& aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);
mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
NS_NewTimerWithCallback(nsITimerCallback* aCallback,
                        const mozilla::TimeDuration& aDelay,
                        uint32_t aType,
                        nsIEventTarget* aTarget = nullptr);

nsresult
NS_NewTimerWithFuncCallback(nsITimer** aTimer,
                            nsTimerCallbackFunc aCallback,
                            void* aClosure,
                            uint32_t aDelay,
                            uint32_t aType,
                            const char* aNameString,
                            nsIEventTarget* aTarget = nullptr);
mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
                            void* aClosure,
                            uint32_t aDelay,
                            uint32_t aType,
                            const char* aNameString,
                            nsIEventTarget* aTarget = nullptr);

nsresult
NS_NewTimerWithFuncCallback(nsITimer** aTimer,
                            nsTimerCallbackFunc aCallback,
                            void* aClosure,
                            uint32_t aDelay,
                            uint32_t aType,
                            nsTimerNameCallbackFunc aNameCallback,
                            nsIEventTarget* aTarget = nullptr);
mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
                            void* aClosure,
                            uint32_t aDelay,
                            uint32_t aType,
                            nsTimerNameCallbackFunc aNameCallback,
                            nsIEventTarget* aTarget = nullptr);

#define NS_TIMER_CONTRACTID "@mozilla.org/timer;1"
#define NS_TIMER_CALLBACK_TOPIC "timer-callback"
%}