From ccbbdd366e114ebc4782555928aa84ed5c8987f6 Mon Sep 17 00:00:00 2001 From: Steve O'Brien Date: Wed, 7 Oct 2015 06:23:01 -0700 Subject: [PATCH] Singleton: un-inline initialization-time-only methods Summary: Move some methods which are generally only used during initialization time (registration, eager-init functions) from the header to the .cpp file Reviewed By: @luciang Differential Revision: D2513043 fb-gh-sync-id: 58d1f6e0d158d805a12b8d267421927b3cfc6118 --- folly/Singleton.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++ folly/Singleton.h | 95 +++------------------------------------------ 2 files changed, 100 insertions(+), 90 deletions(-) diff --git a/folly/Singleton.cpp b/folly/Singleton.cpp index 10290971..5e4e88be 100644 --- a/folly/Singleton.cpp +++ b/folly/Singleton.cpp @@ -56,6 +56,101 @@ FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper; SingletonVault::~SingletonVault() { destroyInstances(); } +void SingletonVault::registerSingleton(detail::SingletonHolderBase* entry) { + RWSpinLock::ReadHolder rh(&stateMutex_); + + stateCheck(SingletonVaultState::Running); + + if (UNLIKELY(registrationComplete_)) { + throw std::logic_error( + "Registering singleton after registrationComplete()."); + } + + RWSpinLock::ReadHolder rhMutex(&mutex_); + CHECK_THROW(singletons_.find(entry->type()) == singletons_.end(), + std::logic_error); + + RWSpinLock::UpgradedHolder wh(&mutex_); + singletons_[entry->type()] = entry; +} + +void SingletonVault::addEagerInitSingleton(detail::SingletonHolderBase* entry) { + RWSpinLock::ReadHolder rh(&stateMutex_); + + stateCheck(SingletonVaultState::Running); + + if (UNLIKELY(registrationComplete_)) { + throw std::logic_error( + "Registering for eager-load after registrationComplete()."); + } + + RWSpinLock::ReadHolder rhMutex(&mutex_); + CHECK_THROW(singletons_.find(entry->type()) != singletons_.end(), + std::logic_error); + + RWSpinLock::UpgradedHolder wh(&mutex_); + eagerInitSingletons_.insert(entry); +} + +void SingletonVault::registrationComplete() { + RequestContext::saveContext(); + std::atexit([](){ SingletonVault::singleton()->destroyInstances(); }); + + RWSpinLock::WriteHolder wh(&stateMutex_); + + stateCheck(SingletonVaultState::Running); + + if (type_ == Type::Strict) { + for (const auto& p : singletons_) { + if (p.second->hasLiveInstance()) { + throw std::runtime_error( + "Singleton created before registration was complete."); + } + } + } + + registrationComplete_ = true; +} + +void SingletonVault::doEagerInit() { + std::unordered_set singletonSet; + { + RWSpinLock::ReadHolder rh(&stateMutex_); + stateCheck(SingletonVaultState::Running); + if (UNLIKELY(!registrationComplete_)) { + throw std::logic_error("registrationComplete() not yet called"); + } + singletonSet = eagerInitSingletons_; // copy set of pointers + } + + for (auto *single : singletonSet) { + single->createInstance(); + } +} + +Future SingletonVault::doEagerInitVia(Executor* exe) { + std::unordered_set singletonSet; + { + RWSpinLock::ReadHolder rh(&stateMutex_); + stateCheck(SingletonVaultState::Running); + if (UNLIKELY(!registrationComplete_)) { + throw std::logic_error("registrationComplete() not yet called"); + } + singletonSet = eagerInitSingletons_; // copy set of pointers + } + + std::vector> resultFutures; + for (auto* single : singletonSet) { + resultFutures.emplace_back(via(exe).then([single] { + if (!single->creationStarted()) { + single->createInstance(); + } + })); + } + + return collectAll(resultFutures).via(exe).then(); +} + void SingletonVault::destroyInstances() { RWSpinLock::WriteHolder state_wh(&stateMutex_); diff --git a/folly/Singleton.h b/folly/Singleton.h index f3569594..ffccd675 100644 --- a/folly/Singleton.h +++ b/folly/Singleton.h @@ -318,68 +318,18 @@ class SingletonVault { // registration is not complete. If validations succeeds, // register a singleton of a given type with the create and teardown // functions. - void registerSingleton(detail::SingletonHolderBase* entry) { - RWSpinLock::ReadHolder rh(&stateMutex_); - - stateCheck(SingletonVaultState::Running); - - if (UNLIKELY(registrationComplete_)) { - throw std::logic_error( - "Registering singleton after registrationComplete()."); - } - - RWSpinLock::ReadHolder rhMutex(&mutex_); - CHECK_THROW(singletons_.find(entry->type()) == singletons_.end(), - std::logic_error); - - RWSpinLock::UpgradedHolder wh(&mutex_); - singletons_[entry->type()] = entry; - } + void registerSingleton(detail::SingletonHolderBase* entry); /** * Called by `Singleton.shouldEagerInit()` to ensure the instance * is built when `doEagerInit[Via]` is called; see those methods * for more info. */ - void addEagerInitSingleton(detail::SingletonHolderBase* entry) { - RWSpinLock::ReadHolder rh(&stateMutex_); - - stateCheck(SingletonVaultState::Running); - - if (UNLIKELY(registrationComplete_)) { - throw std::logic_error( - "Registering for eager-load after registrationComplete()."); - } - - RWSpinLock::ReadHolder rhMutex(&mutex_); - CHECK_THROW(singletons_.find(entry->type()) != singletons_.end(), - std::logic_error); - - RWSpinLock::UpgradedHolder wh(&mutex_); - eagerInitSingletons_.insert(entry); - } + void addEagerInitSingleton(detail::SingletonHolderBase* entry); // Mark registration is complete; no more singletons can be // registered at this point. - void registrationComplete() { - RequestContext::saveContext(); - std::atexit([](){ SingletonVault::singleton()->destroyInstances(); }); - - RWSpinLock::WriteHolder wh(&stateMutex_); - - stateCheck(SingletonVaultState::Running); - - if (type_ == Type::Strict) { - for (const auto& p : singletons_) { - if (p.second->hasLiveInstance()) { - throw std::runtime_error( - "Singleton created before registration was complete."); - } - } - } - - registrationComplete_ = true; - } + void registrationComplete(); /** * Initialize all singletons which were marked as eager-initialized @@ -387,49 +337,14 @@ class SingletonVault { * from constructors / create functions, as is the usual case when calling * for example `Singleton::get_weak()`. */ - void doEagerInit() { - std::unordered_set singletonSet; - { - RWSpinLock::ReadHolder rh(&stateMutex_); - stateCheck(SingletonVaultState::Running); - if (UNLIKELY(!registrationComplete_)) { - throw std::logic_error("registrationComplete() not yet called"); - } - singletonSet = eagerInitSingletons_; // copy set of pointers - } - - for (auto *single : singletonSet) { - single->createInstance(); - } - } + void doEagerInit(); /** * Schedule eager singletons' initializations through the given executor. * Return a future which is fulfilled after all the initialization functions * complete. */ - Future doEagerInitVia(Executor* exe) { - std::unordered_set singletonSet; - { - RWSpinLock::ReadHolder rh(&stateMutex_); - stateCheck(SingletonVaultState::Running); - if (UNLIKELY(!registrationComplete_)) { - throw std::logic_error("registrationComplete() not yet called"); - } - singletonSet = eagerInitSingletons_; // copy set of pointers - } - - std::vector> resultFutures; - for (auto* single : singletonSet) { - resultFutures.emplace_back(via(exe).then([single] { - if (!single->creationStarted()) { - single->createInstance(); - } - })); - } - - return collectAll(resultFutures).via(exe).then(); - } + Future doEagerInitVia(Executor* exe); // Destroy all singletons; when complete, the vault can't create // singletons once again until reenableInstances() is called. -- 2.34.1