Bug 867868 - Implement nsITimer based alarms in HAL fallback. r=jlebar
authorNikhil Marathe <nsm.nikhil@gmail.com>
Tue, 04 Jun 2013 13:30:03 -0700
changeset 141076 0949c968c398571ad924e0b6b051ac6ce9dd3693
parent 141075 c3dc266f985ee896739007011d7a55431d185bf6
child 141077 4b3ac2b997246e8ef414e22f85f8cd4cf54b9b5e
push id3911
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 20:17:26 +0000
treeherdermozilla-aurora@7e26ca8db92b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar
bugs867868
milestone24.0a1
Bug 867868 - Implement nsITimer based alarms in HAL fallback. r=jlebar
hal/fallback/FallbackAlarm.cpp
--- a/hal/fallback/FallbackAlarm.cpp
+++ b/hal/fallback/FallbackAlarm.cpp
@@ -1,28 +1,80 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Hal.h"
 
+#include <algorithm>
+
+#include <nsITimer.h>
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPtr.h"
+#include "nsThreadUtils.h"
+
 namespace mozilla {
 namespace hal_impl {
 
+static void
+TimerCallbackFunc(nsITimer *aTimer, void *aClosure)
+{
+  hal::NotifyAlarmFired();
+}
+
+static StaticRefPtr<nsITimer> sTimer;
+
 bool
 EnableAlarm()
 {
-  return false;
+  static bool initialized = false;
+  if (!initialized) {
+    initialized = true;
+    ClearOnShutdown(&sTimer);
+  }
+
+  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
+  sTimer = timer;
+  MOZ_ASSERT(sTimer);
+  return true;
 }
 
 void
 DisableAlarm()
 {
+  /*
+   * DisableAlarm() may be called after sTimer has been set to null by
+   * ClearOnShutdown().
+   */
+  if (sTimer) {
+    sTimer->Cancel();
+  }
 }
 
 bool
 SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
 {
-  return false;
+  if (!sTimer) {
+    HAL_LOG(("We should have enabled the alarm"));
+    MOZ_ASSERT(false);
+    return false;
+  }
+
+  // Do the math to convert aSeconds and aNanoseconds into milliseconds since
+  // the epoch.
+  int64_t milliseconds = static_cast<int64_t>(aSeconds) * 1000 +
+                         static_cast<int64_t>(aNanoseconds) / 1000000;
+
+  // nsITimer expects relative milliseconds.
+  int64_t relMilliseconds = milliseconds - PR_Now() / 1000;
+
+  // If the alarm time is in the past relative to PR_Now(),
+  // we choose to immediately fire the alarm. Passing 0 means nsITimer will
+  // queue a timeout event immediately.
+  sTimer->InitWithFuncCallback(TimerCallbackFunc, nullptr,
+                               clamped<int64_t>(relMilliseconds, 0, INT32_MAX),
+                               nsITimer::TYPE_ONE_SHOT);
+  return true;
 }
 
 } // hal_impl
 } // namespace mozilla