Commit ee43735c authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Disallow folly::Singletons before main()

Summary:
Make folly::Singleton fail if singleton is requested before registrationComplete. By doing this we disallow any folly::Singleton to be created before main().

Strict mode is still disabled for Python and Hs.

Reviewed By: yfeldblum

Differential Revision: D4121322

fbshipit-source-id: b66c23e24f6a7324cd12ddb77cad960e0950a1aa
parent 9c5b3564
...@@ -225,9 +225,6 @@ void SingletonHolder<T>::createInstance() { ...@@ -225,9 +225,6 @@ void SingletonHolder<T>::createInstance() {
auto state = vault_.state_.rlock(); auto state = vault_.state_.rlock();
if (state->state == SingletonVault::SingletonVaultState::Quiescing) { if (state->state == SingletonVault::SingletonVaultState::Quiescing) {
if (vault_.type_ != SingletonVault::Type::Relaxed) {
LOG(FATAL) << "Requesting singleton after vault was destroyed.";
}
return; return;
} }
......
...@@ -103,12 +103,17 @@ void SingletonVault::registrationComplete() { ...@@ -103,12 +103,17 @@ void SingletonVault::registrationComplete() {
auto state = state_.wlock(); auto state = state_.wlock();
stateCheck(SingletonVaultState::Running, *state); stateCheck(SingletonVaultState::Running, *state);
if (state->registrationComplete) {
return;
}
auto singletons = singletons_.rlock(); auto singletons = singletons_.rlock();
if (type_ == Type::Strict) { if (type_ == Type::Strict) {
for (const auto& p : *singletons) { for (const auto& p : *singletons) {
if (p.second->hasLiveInstance()) { if (p.second->hasLiveInstance()) {
throw std::runtime_error( throw std::runtime_error(
"Singleton created before registration was complete."); "Singleton " + p.first.name() +
" created before registration was complete.");
} }
} }
} }
......
...@@ -348,7 +348,7 @@ class SingletonVault { ...@@ -348,7 +348,7 @@ class SingletonVault {
} }
}; };
explicit SingletonVault(Type type = Type::Relaxed) : type_(type) {} explicit SingletonVault(Type type = Type::Strict) : type_(type) {}
// Destructor is only called by unit tests to check destroyInstances. // Destructor is only called by unit tests to check destroyInstances.
~SingletonVault(); ~SingletonVault();
...@@ -509,7 +509,7 @@ class SingletonVault { ...@@ -509,7 +509,7 @@ class SingletonVault {
folly::Synchronized<State> state_; folly::Synchronized<State> state_;
Type type_{Type::Relaxed}; Type type_;
}; };
// This is the wrapper class that most users actually interact with. // This is the wrapper class that most users actually interact with.
......
...@@ -393,8 +393,8 @@ template <typename T, typename Tag = detail::DefaultTag> ...@@ -393,8 +393,8 @@ template <typename T, typename Tag = detail::DefaultTag>
using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>; using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
TEST(Singleton, SingletonCreationError) { TEST(Singleton, SingletonCreationError) {
SingletonVault::singleton<CreationErrorTag>();
SingletonCreationError<ErrorConstructor> error_once_singleton; SingletonCreationError<ErrorConstructor> error_once_singleton;
SingletonVault::singleton<CreationErrorTag>()->registrationComplete();
// first time should error out // first time should error out
EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error); EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
...@@ -411,6 +411,7 @@ using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>; ...@@ -411,6 +411,7 @@ using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
TEST(Singleton, SingletonConcurrencyStress) { TEST(Singleton, SingletonConcurrencyStress) {
auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>(); auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
SingletonConcurrencyStress<Slowpoke> slowpoke_singleton; SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
vault.registrationComplete();
std::vector<std::thread> ts; std::vector<std::thread> ts;
for (size_t i = 0; i < 100; ++i) { for (size_t i = 0; i < 100; ++i) {
......
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