Bug 1190735 - Remove nsITimer.TYPE_REPEATING_PRECISE. r=froydnj.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 04 Aug 2015 17:30:53 -0700
changeset 288396 e14cb4eb7c0bdd00b20ab6ff212e5f72158b12a9
parent 288395 f58ce99d0d99256512a5e5f7f648a98b9d4b5da7
child 288397 7fa8a6d1f67f9e3ab960de0b539100169e926727
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1190735
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1190735 - Remove nsITimer.TYPE_REPEATING_PRECISE. r=froydnj.
dom/network/NetworkStatsService.jsm
xpcom/tests/unit/test_bug325418.js
xpcom/threads/TimerThread.cpp
xpcom/threads/nsITimer.idl
xpcom/threads/nsTimerImpl.cpp
--- a/dom/network/NetworkStatsService.jsm
+++ b/dom/network/NetworkStatsService.jsm
@@ -122,17 +122,17 @@ this.NetworkStatsService = {
     this.messages.forEach(function(aMsgName) {
       ppmm.addMessageListener(aMsgName, this);
     }, this);
 
     this._db = new NetworkStatsDB();
 
     // Stats for all interfaces are updated periodically
     this.timer.initWithCallback(this, this._db.sampleRate,
-                                Ci.nsITimer.TYPE_REPEATING_PRECISE);
+                                Ci.nsITimer.TYPE_REPEATING_PRECISE_CAN_SKIP);
 
     // Stats not from netd are firstly stored in the cached.
     this.cachedStats = Object.create(null);
     this.cachedStatsDate = new Date();
 
     this.updateQueue = [];
     this.isQueueRunning = false;
 
--- a/xpcom/tests/unit/test_bug325418.js
+++ b/xpcom/tests/unit/test_bug325418.js
@@ -47,15 +47,17 @@ var observer2 = {
 
 function run_test() {
   do_test_pending();
 
   timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
   // Initialize the timer (with some delay), then cancel it.
   gStartTime1 = Date.now();
-  timer.init(observer1, kExpectedDelay1 * 1000, timer.TYPE_REPEATING_PRECISE);
+  timer.init(observer1, kExpectedDelay1 * 1000,
+             timer.TYPE_REPEATING_PRECISE_CAN_SKIP);
   timer.cancel();
 
   // Re-initialize the timer (with a different delay).
   gStartTime2 = Date.now();
-  timer.init(observer2, kExpectedDelay2 * 1000, timer.TYPE_REPEATING_PRECISE);
+  timer.init(observer2, kExpectedDelay2 * 1000,
+             timer.TYPE_REPEATING_PRECISE_CAN_SKIP);
 }
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -704,26 +704,19 @@ TimerThread::PostTimerEvent(already_AddR
     return timer.forget();
   }
 
   if (MOZ_LOG_TEST(GetTimerLog(), LogLevel::Debug)) {
     event->mInitTime = TimeStamp::Now();
   }
 
   // If this is a repeating precise timer, we need to calculate the time for
-  // the next timer to fire before we make the callback.
+  // the next timer to fire before we make the callback. But don't re-arm.
   if (timer->IsRepeatingPrecisely()) {
     timer->SetDelayInternal(timer->mDelay);
-
-    // But only re-arm REPEATING_PRECISE timers.
-    if (timer->mType == nsTimerImpl::TYPE_REPEATING_PRECISE) {
-      if (AddTimerInternal(timer) == -1) {
-        return timer.forget();
-      }
-    }
   }
 
 #ifdef MOZ_TASK_TRACER
   // During the dispatch of TimerEvent, we overwrite the current TraceInfo
   // partially with the info saved in timer earlier, and restore it back by
   // AutoSaveCurTraceInfo.
   AutoSaveCurTraceInfo saveCurTraceInfo;
   (timer->GetTracedTask()).SetTLSTraceInfo();
--- a/xpcom/threads/nsITimer.idl
+++ b/xpcom/threads/nsITimer.idl
@@ -52,68 +52,54 @@ interface nsITimerCallback : nsISupports
  *
  * 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)]
+[scriptable, uuid(c569e813-333f-4b78-8691-13ca5839e10a)]
 interface nsITimer : nsISupports
 {
   /* Timer types */
 
   /**
    * Type of a timer that fires once only.
    */
-  const short TYPE_ONE_SHOT           = 0;
+  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;
-  
+  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
-   * 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.
+   * 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;
+  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, unlike TYPE_REPEATING_PRECISE.  If you want a
-   * non-slack timer, you probably want this one.
+   * afterward, but only once.  This is the only non-slack timer available.
    */
-  const short TYPE_REPEATING_PRECISE_CAN_SKIP  = 3;
+  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
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -286,22 +286,16 @@ nsTimerImpl::SetDelay(uint32_t aDelay)
   if (mCallbackType == CallbackType::Unknown && mType == TYPE_ONE_SHOT) {
     // This may happen if someone tries to re-use a one-shot timer
     // by re-setting delay instead of reinitializing the timer.
     NS_ERROR("nsITimer->SetDelay() called when the "
              "one-shot timer is not set up.");
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  // If we're already repeating precisely, update mTimeout now so that the
-  // new delay takes effect in the future.
-  if (!mTimeout.IsNull() && mType == TYPE_REPEATING_PRECISE) {
-    mTimeout = TimeStamp::Now();
-  }
-
   SetDelayInternal(aDelay);
 
   if (!mFiring && gThread) {
     gThread->TimerDelayChanged(this);
   }
 
   return NS_OK;
 }
@@ -471,20 +465,19 @@ nsTimerImpl::Fire()
 
   mFiring = false;
   mTimerCallbackWhileFiring = nullptr;
 
   MOZ_LOG(GetTimerLog(), LogLevel::Debug,
          ("[this=%p] Took %fms to fire timer callback\n",
           this, (TimeStamp::Now() - now).ToMilliseconds()));
 
-  // Reschedule repeating timers, except REPEATING_PRECISE which already did
-  // that in PostTimerEvent, but make sure that we aren't armed already (which
-  // can happen if the callback reinitialized the timer).
-  if (IsRepeating() && mType != TYPE_REPEATING_PRECISE && !mArmed) {
+  // Reschedule repeating timers, but make sure that we aren't armed already
+  // (which can happen if the callback reinitialized the timer).
+  if (IsRepeating() && !mArmed) {
     if (mType == TYPE_REPEATING_SLACK) {
       SetDelayInternal(mDelay);  // force mTimeout to be recomputed.  For
     }
     // REPEATING_PRECISE_CAN_SKIP timers this has
     // already happened.
     if (gThread) {
       gThread->AddTimer(this);
     }
@@ -494,19 +487,17 @@ nsTimerImpl::Fire()
 void
 nsTimerImpl::SetDelayInternal(uint32_t aDelay)
 {
   TimeDuration delayInterval = TimeDuration::FromMilliseconds(aDelay);
 
   mDelay = aDelay;
 
   TimeStamp now = TimeStamp::Now();
-  if (mTimeout.IsNull() || mType != TYPE_REPEATING_PRECISE) {
-    mTimeout = now;
-  }
+  mTimeout = now;
 
   mTimeout += delayInterval;
 
   if (MOZ_LOG_TEST(GetTimerLog(), LogLevel::Debug)) {
     if (mStart.IsNull()) {
       mStart = now;
     } else {
       mStart2 = now;