author | Nicholas Nethercote <nnethercote@mozilla.com> |
Tue, 04 Aug 2015 17:30:53 -0700 | |
changeset 256718 | e14cb4eb7c0bdd00b20ab6ff212e5f72158b12a9 |
parent 256717 | f58ce99d0d99256512a5e5f7f648a98b9d4b5da7 |
child 256719 | 7fa8a6d1f67f9e3ab960de0b539100169e926727 |
push id | 63407 |
push user | nnethercote@mozilla.com |
push date | Fri, 07 Aug 2015 03:11:51 +0000 |
treeherder | mozilla-inbound@e14cb4eb7c0b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froydnj |
bugs | 1190735 |
milestone | 42.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
|
--- 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;