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
--- 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);