Bug 1208289 - Add SimpleTimer to make setting timeouts in C++ easy. r=jwwang
authorChris Pearce <cpearce@mozilla.com>
Tue, 29 Sep 2015 13:06:11 +1300
changeset 264838 25677e506eefdf118e6ae0e92f5599b65c1e5718
parent 264837 e358d4efa170da4a530b98b576fd60edf4a89471
child 264839 37e7c82c0fc3a8d677f9209cb77de8df77858adb
push id65758
push usercpearce@mozilla.com
push dateTue, 29 Sep 2015 00:09:27 +0000
treeherdermozilla-inbound@37e7c82c0fc3 [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,83 @@ 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<nsIEventTarget> target;
+    mTimer->GetTarget(getter_AddRefs(target));
+    nsCOMPtr<nsIThread> thread(do_QueryInterface(target));
+    MOZ_ASSERT(NS_GetCurrentThread() == thread);
+#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,34 @@ 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:
+  virtual ~SimpleTimer() {}
+  nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget);
+
+  nsRefPtr<nsIRunnable> mTask;
+  nsCOMPtr<nsITimer> mTimer;
+};
+
 } // end namespace mozilla
 
 #endif