Commit ccbbdd36 authored by Steve O'Brien's avatar Steve O'Brien Committed by facebook-github-bot-4

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
parent c12818f9
...@@ -56,6 +56,101 @@ FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper; ...@@ -56,6 +56,101 @@ FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
SingletonVault::~SingletonVault() { destroyInstances(); } 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<detail::SingletonHolderBase*> 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<Unit> SingletonVault::doEagerInitVia(Executor* exe) {
std::unordered_set<detail::SingletonHolderBase*> 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<Future<Unit>> 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() { void SingletonVault::destroyInstances() {
RWSpinLock::WriteHolder state_wh(&stateMutex_); RWSpinLock::WriteHolder state_wh(&stateMutex_);
......
...@@ -318,68 +318,18 @@ class SingletonVault { ...@@ -318,68 +318,18 @@ class SingletonVault {
// registration is not complete. If validations succeeds, // registration is not complete. If validations succeeds,
// register a singleton of a given type with the create and teardown // register a singleton of a given type with the create and teardown
// functions. // functions.
void registerSingleton(detail::SingletonHolderBase* entry) { 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;
}
/** /**
* Called by `Singleton<T>.shouldEagerInit()` to ensure the instance * Called by `Singleton<T>.shouldEagerInit()` to ensure the instance
* is built when `doEagerInit[Via]` is called; see those methods * is built when `doEagerInit[Via]` is called; see those methods
* for more info. * for more info.
*/ */
void addEagerInitSingleton(detail::SingletonHolderBase* entry) { 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);
}
// Mark registration is complete; no more singletons can be // Mark registration is complete; no more singletons can be
// registered at this point. // registered at this point.
void registrationComplete() { 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;
}
/** /**
* Initialize all singletons which were marked as eager-initialized * Initialize all singletons which were marked as eager-initialized
...@@ -387,49 +337,14 @@ class SingletonVault { ...@@ -387,49 +337,14 @@ class SingletonVault {
* from constructors / create functions, as is the usual case when calling * from constructors / create functions, as is the usual case when calling
* for example `Singleton<Foo>::get_weak()`. * for example `Singleton<Foo>::get_weak()`.
*/ */
void doEagerInit() { void doEagerInit();
std::unordered_set<detail::SingletonHolderBase*> 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();
}
}
/** /**
* Schedule eager singletons' initializations through the given executor. * Schedule eager singletons' initializations through the given executor.
* Return a future which is fulfilled after all the initialization functions * Return a future which is fulfilled after all the initialization functions
* complete. * complete.
*/ */
Future<Unit> doEagerInitVia(Executor* exe) { Future<Unit> doEagerInitVia(Executor* exe);
std::unordered_set<detail::SingletonHolderBase*> 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<Future<Unit>> resultFutures;
for (auto* single : singletonSet) {
resultFutures.emplace_back(via(exe).then([single] {
if (!single->creationStarted()) {
single->createInstance();
}
}));
}
return collectAll(resultFutures).via(exe).then();
}
// Destroy all singletons; when complete, the vault can't create // Destroy all singletons; when complete, the vault can't create
// singletons once again until reenableInstances() is called. // singletons once again until reenableInstances() is called.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment