From ee43735cc06a4243e6676b332035927715643be7 Mon Sep 17 00:00:00 2001 From: Andrii Grynenko Date: Tue, 29 Nov 2016 15:34:43 -0800 Subject: [PATCH] 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 --- folly/Singleton-inl.h | 3 --- folly/Singleton.cpp | 7 ++++++- folly/Singleton.h | 4 ++-- folly/test/SingletonTest.cpp | 3 ++- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/folly/Singleton-inl.h b/folly/Singleton-inl.h index 4a6c071b..a0c8cd93 100644 --- a/folly/Singleton-inl.h +++ b/folly/Singleton-inl.h @@ -225,9 +225,6 @@ void SingletonHolder::createInstance() { auto state = vault_.state_.rlock(); if (state->state == SingletonVault::SingletonVaultState::Quiescing) { - if (vault_.type_ != SingletonVault::Type::Relaxed) { - LOG(FATAL) << "Requesting singleton after vault was destroyed."; - } return; } diff --git a/folly/Singleton.cpp b/folly/Singleton.cpp index 5e89442c..6a240181 100644 --- a/folly/Singleton.cpp +++ b/folly/Singleton.cpp @@ -103,12 +103,17 @@ void SingletonVault::registrationComplete() { auto state = state_.wlock(); stateCheck(SingletonVaultState::Running, *state); + if (state->registrationComplete) { + return; + } + auto singletons = singletons_.rlock(); if (type_ == Type::Strict) { for (const auto& p : *singletons) { if (p.second->hasLiveInstance()) { throw std::runtime_error( - "Singleton created before registration was complete."); + "Singleton " + p.first.name() + + " created before registration was complete."); } } } diff --git a/folly/Singleton.h b/folly/Singleton.h index c377f3ad..9c575ed7 100644 --- a/folly/Singleton.h +++ b/folly/Singleton.h @@ -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. ~SingletonVault(); @@ -509,7 +509,7 @@ class SingletonVault { folly::Synchronized state_; - Type type_{Type::Relaxed}; + Type type_; }; // This is the wrapper class that most users actually interact with. diff --git a/folly/test/SingletonTest.cpp b/folly/test/SingletonTest.cpp index aa068911..40e12b98 100644 --- a/folly/test/SingletonTest.cpp +++ b/folly/test/SingletonTest.cpp @@ -393,8 +393,8 @@ template using SingletonCreationError = Singleton; TEST(Singleton, SingletonCreationError) { - SingletonVault::singleton(); SingletonCreationError error_once_singleton; + SingletonVault::singleton()->registrationComplete(); // first time should error out EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error); @@ -411,6 +411,7 @@ using SingletonConcurrencyStress = Singleton ; TEST(Singleton, SingletonConcurrencyStress) { auto& vault = *SingletonVault::singleton(); SingletonConcurrencyStress slowpoke_singleton; + vault.registrationComplete(); std::vector ts; for (size_t i = 0; i < 100; ++i) { -- 2.34.1