Bug 1401412 - Destroy this singleton during XPCOM shutdown. r=smaug
authorBlake Kaplan <mrbkap@gmail.com>
Tue, 19 Sep 2017 17:38:05 -0700
changeset 431604 5a44548cb570c0cc7fd5c188f5f7694a11e66fa4
parent 431603 fd7e2ce2fc920893e864191b19477cd2a9f5cd89
child 431605 dff1e1774422c12aacff69538936e88f0ff95c85
push id7785
push userryanvm@gmail.com
push dateThu, 21 Sep 2017 13:39:55 +0000
treeherdermozilla-beta@06d4034a8a03 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1401412
milestone57.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 1401412 - Destroy this singleton during XPCOM shutdown. r=smaug Unfortunately, this needed some additional trickery in order to keep its constructor "private". I stole this trick from [1]. With this patch, we tear down the statistics object during XPCOM shutdown intead of after it. I don't believe that we need the object to live past the ClearOnShutdown destructors. [1] http://rienajouter.blogspot.com/2014/10/makeshared-and-makeunique-for-classes.html MozReview-Commit-ID: JsiN6Bq9Yp4
xpcom/threads/InputEventStatistics.cpp
xpcom/threads/InputEventStatistics.h
--- a/xpcom/threads/InputEventStatistics.cpp
+++ b/xpcom/threads/InputEventStatistics.cpp
@@ -11,17 +11,17 @@
 namespace mozilla {
 
 TimeDuration
 InputEventStatistics::TimeDurationCircularBuffer::GetMean()
 {
   return mTotal / (int64_t)mSize;
 }
 
-InputEventStatistics::InputEventStatistics()
+InputEventStatistics::InputEventStatistics(ConstructorCookie&&)
   : mEnable(false)
 {
   MOZ_ASSERT(Preferences::IsServiceAvailable());
   uint32_t inputDuration =
     Preferences::GetUint("input_event_queue.default_duration_per_event",
                          sDefaultInputDuration);
 
   TimeDuration defaultDuration = TimeDuration::FromMilliseconds(inputDuration);
--- a/xpcom/threads/InputEventStatistics.h
+++ b/xpcom/threads/InputEventStatistics.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=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/. */
 
 #if !defined(InputEventStatistics_h_)
 #define InputEventStatistics_h_
 
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TimeStamp.h"
 
 namespace mozilla {
 
 class InputEventStatistics
 {
@@ -59,26 +60,37 @@ class InputEventStatistics
     TimeDuration GetMean();
   };
 
   UniquePtr<TimeDurationCircularBuffer> mLastInputDurations;
   TimeDuration mMaxInputDuration;
   TimeDuration mMinInputDuration;
   bool mEnable;
 
-  InputEventStatistics();
+  // We'd like to have our constructor and destructor be private to enforce our
+  // singleton, but because UniquePtr needs to be able to destruct our class we
+  // can't. This is a trick that ensures that we're the only code that can
+  // construct ourselves: nobody else can access ConstructorCookie and therefore
+  // nobody else can construct an InputEventStatistics.
+  struct ConstructorCookie {};
+
+public:
+  explicit InputEventStatistics(ConstructorCookie&&);
   ~InputEventStatistics()
   {
   }
 
-public:
   static InputEventStatistics& Get()
   {
-    static InputEventStatistics sInstance;
-    return sInstance;
+    static UniquePtr<InputEventStatistics> sInstance;
+    if (!sInstance) {
+      sInstance = MakeUnique<InputEventStatistics>(ConstructorCookie());
+      ClearOnShutdown(&sInstance);
+    }
+    return *sInstance;
   }
 
   void UpdateInputDuration(TimeDuration aDuration)
   {
     if (!mEnable) {
       return;
     }
     mLastInputDurations->Insert(aDuration);