Bug 1208289 - Add SimpleTimer to make setting timeouts in C++ easy. r=jwwang
authorChris Pearce <cpearce@mozilla.com>
Mon, 28 Sep 2015 14:03:15 +1300
changeset 264589 bc6762f527751c6ff993f55d54344c5a0dfcf721
parent 264588 9f73b03732fcd4902ddf5f8cb8f3dc6dea1eeaf0
child 264590 28ede868e68c3f5e535f0d81af9d9ca0a871090d
push id65685
push usercpearce@mozilla.com
push dateMon, 28 Sep 2015 01:03:51 +0000
treeherdermozilla-inbound@28ede868e68c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1208289
milestone44.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 1208289 - Add SimpleTimer to make setting timeouts in C++ easy. r=jwwang
dom/media/VideoUtils.cpp
dom/media/VideoUtils.h
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -364,9 +364,82 @@ CreateMediaDecodeTaskQueue()
 already_AddRefed<FlushableTaskQueue>
 CreateFlushableMediaDecodeTaskQueue()
 {
   nsRefPtr<FlushableTaskQueue> queue = new FlushableTaskQueue(
     GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   return queue.forget();
 }
 
+void
+SimpleTimer::Cancel() {
+  if (mTimer) {
+#ifdef DEBUG
+    nsCOMPtr<nsIThread> target;
+    mTimer->GetTarget(getter_AddRefs(target));
+    MOZ_ASSERT(NS_GetCurrentThread() == target);
+#endif
+    mTimer->Cancel();
+    mTimer = nullptr;
+  }
+  mTask = nullptr;
+}
+
+NS_IMETHODIMP
+SimpleTimer::Notify(nsITimer *timer) {
+  nsRefPtr<SimpleTimer> deathGrip(this);
+  if (mTask) {
+    mTask->Run();
+    mTask = nullptr;
+  }
+  return NS_OK;
+}
+
+nsresult
+SimpleTimer::Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
+{
+  nsresult rv;
+
+  // Get target thread first, so we don't have to cancel the timer if it fails.
+  nsCOMPtr<nsIThread> target;
+  if (aTarget) {
+    target = aTarget;
+  } else {
+    rv = NS_GetMainThread(getter_AddRefs(target));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
+  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  // Note: set target before InitWithCallback in case the timer fires before
+  // we change the event target.
+  rv = timer->SetTarget(aTarget);
+  if (NS_FAILED(rv)) {
+    timer->Cancel();
+    return rv;
+  }
+  rv = timer->InitWithCallback(this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  mTimer = timer.forget();
+  mTask = aTask;
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(SimpleTimer, nsITimerCallback)
+
+already_AddRefed<SimpleTimer>
+SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget)
+{
+  nsRefPtr<SimpleTimer> t(new SimpleTimer());
+  if (NS_FAILED(t->Init(aTask, aTimeoutMs, aTarget))) {
+    return nullptr;
+  }
+  return t.forget();
+}
+
 } // end namespace mozilla
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -17,16 +17,18 @@
 #include "nsIThread.h"
 #include "nsSize.h"
 #include "nsRect.h"
 
 #include "nsThreadUtils.h"
 #include "prtime.h"
 #include "AudioSampleFormat.h"
 #include "TimeUnits.h"
+#include "nsITimer.h"
+#include "nsCOMPtr.h"
 
 using mozilla::CheckedInt64;
 using mozilla::CheckedUint64;
 using mozilla::CheckedInt32;
 using mozilla::CheckedUint32;
 
 // This file contains stuff we'd rather put elsewhere, but which is
 // dependent on other changes which we don't want to wait for. We plan to
@@ -296,11 +298,33 @@ nsRefPtr<GenericPromise> InvokeUntil(Wor
       }
     }
   };
 
   Helper::Iteration(p, aWork, aCondition);
   return p.forget();
 }
 
+// Simple timer to run a runnable after a timeout.
+class SimpleTimer : public nsITimerCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  // Create a new timer to run aTask after aTimeoutMs milliseconds
+  // on thread aTarget. If aTarget is null, task is run on the main thread.
+  static already_AddRefed<SimpleTimer> Create(nsIRunnable* aTask,
+                                              uint32_t aTimeoutMs,
+                                              nsIThread* aTarget = nullptr);
+  void Cancel();
+
+  NS_IMETHOD Notify(nsITimer *timer) override;
+
+private:
+  nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget);
+
+  nsRefPtr<nsIRunnable> mTask;
+  nsCOMPtr<nsITimer> mTimer;
+};
+
 } // end namespace mozilla
 
 #endif