From 736c0e46c4b541597d36f0f9c5ea99cb6ef828d1 Mon Sep 17 00:00:00 2001 From: Chip Turner Date: Thu, 11 Sep 2014 17:36:50 -0700 Subject: [PATCH] Add non-strict mode to folly::Singleton Summary: It is difficult to guarantee every binary can call registrationComplete; for now, support a mode where we don't enforce the strict registration lifecycle. In the fullness of time, we can make strictness the default. Test Plan: runtests Reviewed By: lins@fb.com Subscribers: lins, anca, njormrod FB internal diff: D1551688 --- folly/experimental/Singleton.h | 27 +++++++++++++++-------- folly/experimental/test/SingletonTest.cpp | 8 +++---- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/folly/experimental/Singleton.h b/folly/experimental/Singleton.h index c861e1bc..73625a99 100644 --- a/folly/experimental/Singleton.h +++ b/folly/experimental/Singleton.h @@ -163,7 +163,9 @@ class TypeDescriptorHasher { class SingletonVault { public: - SingletonVault() {}; + enum class Type { Strict, Relaxed }; + + explicit SingletonVault(Type type = Type::Relaxed) : type_(type) {} ~SingletonVault(); typedef std::function TeardownFunc; @@ -176,7 +178,7 @@ class SingletonVault { TeardownFunc teardown) { std::lock_guard guard(mutex_); - CHECK_THROW(state_ == SingletonVaultState::Registering, std::logic_error); + stateCheck(SingletonVaultState::Registering); CHECK_THROW(singletons_.find(type) == singletons_.end(), std::logic_error); auto& entry = singletons_[type]; if (!entry) { @@ -196,7 +198,7 @@ class SingletonVault { // registered at this point. void registrationComplete() { std::lock_guard guard(mutex_); - CHECK_THROW(state_ == SingletonVaultState::Registering, std::logic_error); + stateCheck(SingletonVaultState::Registering); state_ = SingletonVaultState::Running; } @@ -259,6 +261,13 @@ class SingletonVault { Living, }; + void stateCheck(SingletonVaultState expected, + const char* msg="Unexpected singleton state change") { + if (type_ == Type::Strict && expected != state_) { + throw std::logic_error(msg); + } + } + // An actual instance of a singleton, tracking the instance itself, // its state as described above, and the create and teardown // functions. @@ -292,12 +301,11 @@ class SingletonVault { SingletonEntry* get_entry(detail::TypeDescriptor type, std::unique_lock* lock) { // mutex must be held when calling this function - if (state_ != SingletonVaultState::Running) { - throw std::logic_error( - "Attempt to load a singleton before " - "SingletonVault::registrationComplete was called (hint: you probably " - "didn't call initFacebook)"); - } + stateCheck( + SingletonVaultState::Running, + "Attempt to load a singleton before " + "SingletonVault::registrationComplete was called (hint: you probably " + "didn't call initFacebook)"); auto it = singletons_.find(type); if (it == singletons_.end()) { @@ -357,6 +365,7 @@ class SingletonVault { detail::TypeDescriptorHasher> singletons_; std::vector creation_order_; SingletonVaultState state_ = SingletonVaultState::Registering; + Type type_ = Type::Relaxed; }; // This is the wrapper class that most users actually interact with. diff --git a/folly/experimental/test/SingletonTest.cpp b/folly/experimental/test/SingletonTest.cpp index 3c3f1916..9c28e5ec 100644 --- a/folly/experimental/test/SingletonTest.cpp +++ b/folly/experimental/test/SingletonTest.cpp @@ -174,7 +174,7 @@ TEST(Singleton, NamedUsage) { // Some pathological cases such as getting unregistered singletons, // double registration, etc. TEST(Singleton, NaughtyUsage) { - SingletonVault vault; + SingletonVault vault(SingletonVault::Type::Strict); vault.registrationComplete(); // Unregistered. @@ -188,10 +188,10 @@ TEST(Singleton, NaughtyUsage) { }(), std::logic_error); - EXPECT_THROW([]() { Singleton watchdog_singleton; }(), - std::logic_error); + // Default vault is non-strict; this should work. + Singleton global_watchdog_singleton; - SingletonVault vault_2; + SingletonVault vault_2(SingletonVault::Type::Strict); EXPECT_THROW(Singleton::get(&vault_2), std::logic_error); Singleton watchdog_singleton(nullptr, nullptr, &vault_2); // double registration -- 2.34.1