From e1b2f2ef09f06ffb890fa52db5cd5ce50dd4bfe8 Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Wed, 1 Feb 2017 14:08:46 -0800 Subject: [PATCH] Bug 1337537 - Make a SystemGroup singleton (r=ehsan) MozReview-Commit-ID: Jnwrr49daeM --- xpcom/build/XPCOMInit.cpp | 10 +++++ xpcom/threads/SystemGroup.cpp | 76 +++++++++++++++++++++++++++++++++-- xpcom/threads/SystemGroup.h | 11 ++++- 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index e30220c9f410..71c1988c9d8c 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -130,6 +130,7 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**); #include "mozilla/Services.h" #include "mozilla/Omnijar.h" #include "mozilla/HangMonitor.h" +#include "mozilla/SystemGroup.h" #include "mozilla/Telemetry.h" #include "mozilla/BackgroundHangMonitor.h" @@ -553,6 +554,9 @@ NS_InitXPCOM2(nsIServiceManager** aResult, return rv; } + // Init the SystemGroup for dispatching main thread runnables. + SystemGroup::InitStatic(); + // Set up the timer globals/timer thread rv = nsTimerImpl::Startup(); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -786,6 +790,9 @@ NS_InitMinimalXPCOM() return rv; } + // Init the SystemGroup for dispatching main thread runnables. + SystemGroup::InitStatic(); + // Set up the timer globals/timer thread. rv = nsTimerImpl::Startup(); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -1065,6 +1072,9 @@ ShutdownXPCOM(nsIServiceManager* aServMgr) nsComponentManagerImpl::gComponentManager = nullptr; nsCategoryManager::Destroy(); + // Shut down SystemGroup for main thread dispatching. + SystemGroup::Shutdown(); + NS_ShutdownAtomTable(); NS_IF_RELEASE(gDebug); diff --git a/xpcom/threads/SystemGroup.cpp b/xpcom/threads/SystemGroup.cpp index c0641f1afcc3..c67bb6e454c0 100644 --- a/xpcom/threads/SystemGroup.cpp +++ b/xpcom/threads/SystemGroup.cpp @@ -7,21 +7,91 @@ #include "SystemGroup.h" #include "mozilla/Move.h" +#include "mozilla/UniquePtr.h" #include "nsINamed.h" using namespace mozilla; +class SystemGroupImpl final : public ValidatingDispatcher +{ +public: + SystemGroupImpl(); + ~SystemGroupImpl() {} + + static void InitStatic(); + static void ShutdownStatic(); + static SystemGroupImpl* Get(); + + NS_METHOD_(MozExternalRefCountType) AddRef(void) + { + return 2; + } + NS_METHOD_(MozExternalRefCountType) Release(void) + { + return 1; + } + +private: + static UniquePtr sSingleton; +}; + +UniquePtr SystemGroupImpl::sSingleton; + +SystemGroupImpl::SystemGroupImpl() +{ + CreateEventTargets(/* aNeedValidation = */ true); +} + +/* static */ void +SystemGroupImpl::InitStatic() +{ + MOZ_ASSERT(!sSingleton); + MOZ_ASSERT(NS_IsMainThread()); + sSingleton = MakeUnique(); +} + +/* static */ void +SystemGroupImpl::ShutdownStatic() +{ + sSingleton->Shutdown(); + sSingleton = nullptr; +} + +/* static */ SystemGroupImpl* +SystemGroupImpl::Get() +{ + MOZ_ASSERT(sSingleton); + return sSingleton.get(); +} + +void +SystemGroup::InitStatic() +{ + SystemGroupImpl::InitStatic(); +} + +void +SystemGroup::Shutdown() +{ + SystemGroupImpl::ShutdownStatic(); +} + /* static */ nsresult SystemGroup::Dispatch(const char* aName, TaskCategory aCategory, already_AddRefed&& aRunnable) { - return Dispatcher::UnlabeledDispatch(aName, aCategory, Move(aRunnable)); + return SystemGroupImpl::Get()->Dispatch(aName, aCategory, Move(aRunnable)); } /* static */ nsIEventTarget* SystemGroup::EventTargetFor(TaskCategory aCategory) { - nsCOMPtr main = do_GetMainThread(); - return main; + return SystemGroupImpl::Get()->EventTargetFor(aCategory); +} + +/* static */ AbstractThread* +SystemGroup::AbstractMainThreadFor(TaskCategory aCategory) +{ + return SystemGroupImpl::Get()->AbstractMainThreadFor(aCategory); } diff --git a/xpcom/threads/SystemGroup.h b/xpcom/threads/SystemGroup.h index d27eba268e56..1e94b7c25815 100644 --- a/xpcom/threads/SystemGroup.h +++ b/xpcom/threads/SystemGroup.h @@ -8,6 +8,7 @@ #define mozilla_SystemGroup_h #include "mozilla/TaskCategory.h" +#include "mozilla/Dispatcher.h" // The SystemGroup should be used for dispatching runnables that don't need to // touch web content. Runnables dispatched to the SystemGroup are run in order @@ -16,7 +17,8 @@ namespace mozilla { -class SystemGroup { +class SystemGroup +{ public: // This method is safe to use from any thread. static nsresult Dispatch(const char* aName, @@ -25,6 +27,13 @@ class SystemGroup { // This method is safe to use from any thread. static nsIEventTarget* EventTargetFor(TaskCategory aCategory); + + // Must be called on the main thread. The AbstractThread can always be used + // off the main thread. + static AbstractThread* AbstractMainThreadFor(TaskCategory aCategory); + + static void InitStatic(); + static void Shutdown(); }; } // namespace mozilla