From b73c1c58f3ee906351086bbd8e53a43e6ed4e477 Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 16 Oct 2015 19:00:15 -0400 Subject: [PATCH] Bug 1213273 - Use a chromium Task instead of an nsITimer for the timeout in TaskThrottler. r=mstange --HG-- extra : rebase_source : 2ddc7714fff1d62aa394332fdafd8c2e5c97b065 extra : source : 00f7757e184487dc77e1be0e07ef7c4e9360e6c3 --- gfx/layers/apz/src/TaskThrottler.cpp | 52 ++++++++++++++++------------ gfx/layers/apz/src/TaskThrottler.h | 7 ++-- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/gfx/layers/apz/src/TaskThrottler.cpp b/gfx/layers/apz/src/TaskThrottler.cpp index afa098d829d6..399b4e4ecf7e 100644 --- a/gfx/layers/apz/src/TaskThrottler.cpp +++ b/gfx/layers/apz/src/TaskThrottler.cpp @@ -6,9 +6,7 @@ #include "TaskThrottler.h" -#include "mozilla/layers/APZThreadUtils.h" // for NewTimerCallback -#include "nsComponentManagerUtils.h" // for do_CreateInstance -#include "nsITimer.h" +#include "base/message_loop.h" #define TASK_LOG(...) // #define TASK_LOG(...) printf_stderr("TASK: " __VA_ARGS__) @@ -23,17 +21,14 @@ TaskThrottler::TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aM , mStartTime(aTimeStamp) , mMaxWait(aMaxWait) , mMean(1) - , mTimer(do_CreateInstance(NS_TIMER_CONTRACTID)) + , mTimeoutTask(nullptr) { - // The TaskThrottler must be created on the main thread (or some nsITimer- - // compatible thread) for the nsITimer to work properly. In particular, - // creating it on the Compositor thread doesn't work. - MOZ_ASSERT(NS_IsMainThread()); } TaskThrottler::~TaskThrottler() { - mTimer->Cancel(); + // The timeout task holds a strong reference to the TaskThrottler, so if the + // TaskThrottler is being destroyed, there's no need to cancel the task. } void @@ -53,17 +48,9 @@ TaskThrottler::PostTask(const tracked_objects::Location& aLocation, // Make sure the queued task is sent after mMaxWait time elapses, // even if we don't get a TaskComplete() until then. TimeDuration timeout = mMaxWait - TimeSinceLastRequest(aTimeStamp, lock); - TimeStamp timeoutTime = mStartTime + mMaxWait; - RefPtr refPtrThis = this; - mTimer->InitWithCallback(NewTimerCallback( - [refPtrThis, timeoutTime]() - { - MonitorAutoLock lock(refPtrThis->mMonitor); - if (refPtrThis->mQueuedTask) { - refPtrThis->RunQueuedTask(timeoutTime, lock); - } - }), - timeout.ToMilliseconds(), nsITimer::TYPE_ONE_SHOT); + mTimeoutTask = NewRunnableMethod(this, &TaskThrottler::OnTimeout); + MessageLoop::current()->PostDelayedTask(FROM_HERE, mTimeoutTask, + timeout.ToMilliseconds()); return; } // we've been waiting for more than the max-wait limit, so just fall through @@ -75,6 +62,18 @@ TaskThrottler::PostTask(const tracked_objects::Location& aLocation, mOutstanding = true; } +void +TaskThrottler::OnTimeout() +{ + MonitorAutoLock lock(mMonitor); + if (mQueuedTask) { + RunQueuedTask(TimeStamp::Now(), lock); + } + // The message loop will delete the posted timeout task. Make sure we don't + // keep a dangling pointer to it. + mTimeoutTask = nullptr; +} + void TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp) { @@ -88,7 +87,7 @@ TaskThrottler::TaskComplete(const TimeStamp& aTimeStamp) if (mQueuedTask) { RunQueuedTask(aTimeStamp, lock); - mTimer->Cancel(); + CancelTimeoutTask(lock); } else { mOutstanding = false; } @@ -126,7 +125,16 @@ TaskThrottler::CancelPendingTask(const MonitorAutoLock& aProofOfLock) TASK_LOG("%p cancelling task %p\n", this, mQueuedTask.get()); mQueuedTask->Cancel(); mQueuedTask = nullptr; - mTimer->Cancel(); + CancelTimeoutTask(aProofOfLock); + } +} + +void +TaskThrottler::CancelTimeoutTask(const MonitorAutoLock& aProofOfLock) +{ + if (mTimeoutTask) { + mTimeoutTask->Cancel(); + mTimeoutTask = nullptr; // the MessageLoop will destroy it } } diff --git a/gfx/layers/apz/src/TaskThrottler.h b/gfx/layers/apz/src/TaskThrottler.h index f86f1956965c..50a799bb6ab2 100644 --- a/gfx/layers/apz/src/TaskThrottler.h +++ b/gfx/layers/apz/src/TaskThrottler.h @@ -18,8 +18,6 @@ #include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING #include "nsTArray.h" // for nsTArray -class nsITimer; - namespace tracked_objects { class Location; } // namespace tracked_objects @@ -102,7 +100,8 @@ private: TimeStamp mStartTime; TimeDuration mMaxWait; RollingMean mMean; - nsCOMPtr mTimer; + CancelableTask* mTimeoutTask; // not owned because it's posted to a MessageLoop + // which deletes it ~TaskThrottler(); void RunQueuedTask(const TimeStamp& aTimeStamp, @@ -110,6 +109,8 @@ private: void CancelPendingTask(const MonitorAutoLock& aProofOfLock); TimeDuration TimeSinceLastRequest(const TimeStamp& aTimeStamp, const MonitorAutoLock& aProofOfLock); + void OnTimeout(); + void CancelTimeoutTask(const MonitorAutoLock& aProofOfLock); }; } // namespace layers