Disallow folly::Singletons before main()
authorAndrii Grynenko <andrii@fb.com>
Tue, 29 Nov 2016 23:34:43 +0000 (15:34 -0800)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Tue, 29 Nov 2016 23:38:29 +0000 (15:38 -0800)
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
folly/Singleton.cpp
folly/Singleton.h
folly/test/SingletonTest.cpp

index 4a6c071ba4c2d794c4f5bd4a6265eb021b357d19..a0c8cd93094590e2e0752f0569c9c09a2bf74e55 100644 (file)
@@ -225,9 +225,6 @@ void SingletonHolder<T>::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;
   }
 
index 5e89442c01e0a2692b10fe5e38e0c306a0c9c0e9..6a240181cedf13abedb9ad8ab18bf59fdf42af02 100644 (file)
@@ -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.");
       }
     }
   }
index c377f3ad02c49c6b3cc2a6f233d7c80371edb15c..9c575ed7cc6d81a12e0924657684ccfeaf776c24 100644 (file)
@@ -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> state_;
 
-  Type type_{Type::Relaxed};
+  Type type_;
 };
 
 // This is the wrapper class that most users actually interact with.
index aa068911840d49e081023538ae0aed83f3cdde7f..40e12b982b07d3f3327a1331350f458eaafaeda8 100644 (file)
@@ -393,8 +393,8 @@ template <typename T, typename Tag = detail::DefaultTag>
 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
 
 TEST(Singleton, SingletonCreationError) {
-  SingletonVault::singleton<CreationErrorTag>();
   SingletonCreationError<ErrorConstructor> error_once_singleton;
+  SingletonVault::singleton<CreationErrorTag>()->registrationComplete();
 
   // first time should error out
   EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
@@ -411,6 +411,7 @@ using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
 TEST(Singleton, SingletonConcurrencyStress) {
   auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
   SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
+  vault.registrationComplete();
 
   std::vector<std::thread> ts;
   for (size_t i = 0; i < 100; ++i) {