Revert "Revert "Using type-tags for test SingletonVaults""
authorAndrii Grynenko <andrii@fb.com>
Fri, 6 Feb 2015 23:48:19 +0000 (15:48 -0800)
committerSara Golemon <sgolemon@fb.com>
Wed, 11 Feb 2015 02:02:00 +0000 (18:02 -0800)
Summary:
This reverts commit 4893c09795ad4b1187518b184ac4812079039988.

Fix unit test in D1823663.

Test Plan: fbconfig -r folly fbmake dbg

Reviewed By: alikhtarov@fb.com

Subscribers: folly-diffs@, yfeldblum

FB internal diff: D1832645

Signature: t1:1832645:1423267466:6012f1d7700d540c7290c29b01b33148cf91183c

folly/experimental/Singleton.cpp
folly/experimental/Singleton.h
folly/experimental/test/SingletonTest.cpp
folly/experimental/test/SingletonVaultCTest.cpp

index 560175fbadc7b78f02fe01831aa53cf979662964..20522b24b449ef78f0a858fd79ab866a5bbbe770 100644 (file)
@@ -86,11 +86,6 @@ void SingletonVault::reenableInstances() {
   state_ = SingletonVaultState::Running;
 }
 
-SingletonVault* SingletonVault::singleton() {
-  static SingletonVault* vault = new SingletonVault();
-  return vault;
-}
-
 void SingletonVault::scheduleDestroyInstances() {
   RequestContext::getStaticContext();
 
index a715a278895fe2c1d4fe5dd435f4a954727f0128..6cb9485712bdcdf51e5951d4cc254df37bedb518 100644 (file)
@@ -399,7 +399,17 @@ class SingletonVault {
 
   // A well-known vault; you can actually have others, but this is the
   // default.
-  static SingletonVault* singleton();
+  static SingletonVault* singleton() {
+    return singleton<>();
+  }
+
+  // Gets singleton vault for any Tag. Non-default tag should be used in unit
+  // tests only.
+  template <typename VaultTag = detail::DefaultTag>
+  static SingletonVault* singleton() {
+    static SingletonVault* vault = new SingletonVault();
+    return vault;
+  }
 
  private:
   // The two stages of life for a vault, as mentioned in the class comment.
@@ -534,7 +544,9 @@ class SingletonVault {
 // singletons.  Create instances of this class in the global scope of
 // type Singleton<T> to register your singleton for later access via
 // Singleton<T>::get().
-template <typename T, typename Tag = detail::DefaultTag>
+template <typename T,
+          typename Tag = detail::DefaultTag,
+          typename VaultTag = detail::DefaultTag /* for testing */>
 class Singleton {
  public:
   typedef std::function<T*(void)> CreateFunc;
@@ -543,9 +555,9 @@ class Singleton {
   // Generally your program life cycle should be fine with calling
   // get() repeatedly rather than saving the reference, and then not
   // call get() during process shutdown.
-  static T* get(SingletonVault* vault = nullptr /* for testing */) {
+  static T* get() {
     return static_cast<T*>(
-      (vault ?: SingletonVault::singleton())->get_ptr(typeDescriptor()));
+      SingletonVault::singleton<VaultTag>()->get_ptr(typeDescriptor()));
   }
 
   // Same as get, but should be preffered to it in the same compilation
@@ -554,7 +566,7 @@ class Singleton {
     if (LIKELY(entry_->state == detail::SingletonEntryState::Living)) {
       return reinterpret_cast<T*>(entry_->instance_ptr);
     } else {
-      return get(vault_);
+      return get();
     }
   }
 
@@ -562,10 +574,9 @@ class Singleton {
   // singleton, you can try to do so with a weak_ptr.  Avoid this when
   // possible but the inability to lock the weak pointer can be a
   // signal that the vault has been destroyed.
-  static std::weak_ptr<T> get_weak(
-      SingletonVault* vault = nullptr /* for testing */) {
+  static std::weak_ptr<T> get_weak() {
     auto weak_void_ptr =
-      (vault ?: SingletonVault::singleton())->get_weak(typeDescriptor());
+      (SingletonVault::singleton<VaultTag>())->get_weak(typeDescriptor());
 
     // This is ugly and inefficient, but there's no other way to do it, because
     // there's no static_pointer_cast for weak_ptr.
@@ -588,7 +599,7 @@ class Singleton {
       }
       return std::static_pointer_cast<T>(shared_void_ptr);
     } else {
-      return get_weak(vault_);
+      return get_weak();
     }
   }
 
@@ -599,26 +610,19 @@ class Singleton {
   T* operator->() { return ptr(); }
 
   explicit Singleton(std::nullptr_t _ = nullptr,
-                     Singleton::TeardownFunc t = nullptr,
-                     SingletonVault* vault = nullptr) :
-      Singleton ([]() { return new T; },
-                 std::move(t),
-                 vault) {
+                     Singleton::TeardownFunc t = nullptr) :
+      Singleton ([]() { return new T; }, std::move(t)) {
   }
 
   explicit Singleton(Singleton::CreateFunc c,
-                     Singleton::TeardownFunc t = nullptr,
-                     SingletonVault* vault = nullptr) {
+                     Singleton::TeardownFunc t = nullptr) {
     if (c == nullptr) {
       throw std::logic_error(
         "nullptr_t should be passed if you want T to be default constructed");
     }
 
-    if (vault == nullptr) {
-      vault = SingletonVault::singleton();
-    }
+    auto vault = SingletonVault::singleton<VaultTag>();
 
-    vault_ = vault;
     entry_ =
       &(vault->registerSingleton(typeDescriptor(), c, getTeardownFunc(t)));
   }
@@ -634,22 +638,18 @@ class Singleton {
   * regular singletons.
   */
   static void make_mock(std::nullptr_t c = nullptr,
-                        typename Singleton<T>::TeardownFunc t = nullptr,
-                        SingletonVault* vault = nullptr /* for testing */ ) {
-    make_mock([]() { return new T; }, t, vault);
+                        typename Singleton<T>::TeardownFunc t = nullptr) {
+    make_mock([]() { return new T; }, t);
   }
 
   static void make_mock(CreateFunc c,
-                        typename Singleton<T>::TeardownFunc t = nullptr,
-                        SingletonVault* vault = nullptr /* for testing */ ) {
+                        typename Singleton<T>::TeardownFunc t = nullptr) {
     if (c == nullptr) {
       throw std::logic_error(
         "nullptr_t should be passed if you want T to be default constructed");
     }
 
-    if (vault == nullptr) {
-      vault = SingletonVault::singleton();
-    }
+    auto vault = SingletonVault::singleton<VaultTag>();
 
     vault->registerMockSingleton(
       typeDescriptor(),
@@ -680,7 +680,6 @@ class Singleton {
   // We rely on the fact that Singleton destructor won't reset this pointer, so
   // it can be "safely" used even after static Singleton object is destroyed.
   detail::SingletonEntry* entry_;
-  SingletonVault* vault_;
 };
 
 }
index 25b270a6eb8f3cb5a96521db8197b6b692beb4c7..57b25f401687537e7bb7671af5074e6335904f2c 100644 (file)
@@ -83,30 +83,34 @@ TEST(Singleton, MissingSingleton) {
                std::out_of_range);
 }
 
+struct BasicUsageTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
+
 // Exercise some basic codepaths ensuring registration order and
 // destruction order happen as expected, that instances are created
 // when expected, etc etc.
 TEST(Singleton, BasicUsage) {
-  SingletonVault vault;
+  auto& vault = *SingletonVault::singleton<BasicUsageTag>();
 
   EXPECT_EQ(vault.registeredSingletonCount(), 0);
-  Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
+  SingletonBasicUsage<Watchdog> watchdog_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 1);
 
-  Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
+  SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 2);
 
   vault.registrationComplete();
 
-  Watchdog* s1 = Singleton<Watchdog>::get(&vault);
+  Watchdog* s1 = SingletonBasicUsage<Watchdog>::get();
   EXPECT_NE(s1, nullptr);
 
-  Watchdog* s2 = Singleton<Watchdog>::get(&vault);
+  Watchdog* s2 = SingletonBasicUsage<Watchdog>::get();
   EXPECT_NE(s2, nullptr);
 
   EXPECT_EQ(s1, s2);
 
-  auto s3 = Singleton<ChildWatchdog>::get(&vault);
+  auto s3 = SingletonBasicUsage<ChildWatchdog>::get();
   EXPECT_NE(s3, nullptr);
   EXPECT_NE(s2, s3);
 
@@ -118,28 +122,38 @@ TEST(Singleton, BasicUsage) {
   EXPECT_EQ(vault.livingSingletonCount(), 0);
 }
 
+struct DirectUsageTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
+
 TEST(Singleton, DirectUsage) {
-  SingletonVault vault;
+  auto& vault = *SingletonVault::singleton<DirectUsageTag>();
 
   EXPECT_EQ(vault.registeredSingletonCount(), 0);
 
   // Verify we can get to the underlying singletons via directly using
   // the singleton definition.
-  Singleton<Watchdog> watchdog(nullptr, nullptr, &vault);
+  SingletonDirectUsage<Watchdog> watchdog;
   struct TestTag {};
-  Singleton<Watchdog, TestTag> named_watchdog(nullptr, nullptr, &vault);
+  SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
   EXPECT_EQ(vault.registeredSingletonCount(), 2);
   vault.registrationComplete();
 
   EXPECT_NE(watchdog.ptr(), nullptr);
-  EXPECT_EQ(watchdog.ptr(), Singleton<Watchdog>::get(&vault));
+  EXPECT_EQ(watchdog.ptr(), SingletonDirectUsage<Watchdog>::get());
   EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
   EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
   EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
+
+  vault.destroyInstances();
 }
 
+struct NamedUsageTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
+
 TEST(Singleton, NamedUsage) {
-  SingletonVault vault;
+  auto& vault = *SingletonVault::singleton<NamedUsageTag>();
 
   EXPECT_EQ(vault.registeredSingletonCount(), 0);
 
@@ -147,96 +161,105 @@ TEST(Singleton, NamedUsage) {
   struct Watchdog1 {};
   struct Watchdog2 {};
   typedef detail::DefaultTag Watchdog3;
-  Singleton<Watchdog, Watchdog1> watchdog1_singleton(nullptr, nullptr, &vault);
+  SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 1);
-  Singleton<Watchdog, Watchdog2> watchdog2_singleton(nullptr, nullptr, &vault);
+  SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 2);
-  Singleton<Watchdog, Watchdog3> watchdog3_singleton(nullptr, nullptr, &vault);
+  SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 3);
 
   vault.registrationComplete();
 
   // Verify our three singletons are distinct and non-nullptr.
-  Watchdog* s1 = Singleton<Watchdog, Watchdog1>::get(&vault);
+  Watchdog* s1 = SingletonNamedUsage<Watchdog, Watchdog1>::get();
   EXPECT_EQ(s1, watchdog1_singleton.ptr());
-  Watchdog* s2 = Singleton<Watchdog, Watchdog2>::get(&vault);
+  Watchdog* s2 = SingletonNamedUsage<Watchdog, Watchdog2>::get();
   EXPECT_EQ(s2, watchdog2_singleton.ptr());
   EXPECT_NE(s1, s2);
-  Watchdog* s3 = Singleton<Watchdog, Watchdog3>::get(&vault);
+  Watchdog* s3 = SingletonNamedUsage<Watchdog, Watchdog3>::get();
   EXPECT_EQ(s3, watchdog3_singleton.ptr());
   EXPECT_NE(s3, s1);
   EXPECT_NE(s3, s2);
 
   // Verify the "default" singleton is the same as the DefaultTag-tagged
   // singleton.
-  Watchdog* s4 = Singleton<Watchdog>::get(&vault);
+  Watchdog* s4 = SingletonNamedUsage<Watchdog>::get();
   EXPECT_EQ(s4, watchdog3_singleton.ptr());
+
+  vault.destroyInstances();
 }
 
+struct NaughtyUsageTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
+struct NaughtyUsageTag2 {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
+
 // Some pathological cases such as getting unregistered singletons,
 // double registration, etc.
 TEST(Singleton, NaughtyUsage) {
-  SingletonVault vault(SingletonVault::Type::Strict);
+  auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
+
   vault.registrationComplete();
 
   // Unregistered.
   EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
-  EXPECT_THROW(Singleton<Watchdog>::get(&vault), std::out_of_range);
-
-  // Registring singletons after registrationComplete called.
-  EXPECT_THROW([&vault]() {
-                 Singleton<Watchdog> watchdog_singleton(
-                     nullptr, nullptr, &vault);
-               }(),
-               std::logic_error);
-
-  SingletonVault vault_2(SingletonVault::Type::Strict);
-  EXPECT_THROW(Singleton<Watchdog>::get(&vault_2), std::logic_error);
-  Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault_2);
+  EXPECT_THROW(SingletonNaughtyUsage<Watchdog>::get(), std::out_of_range);
+
+  vault.destroyInstances();
+
+  auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
+
+  EXPECT_THROW(SingletonNaughtyUsage2<Watchdog>::get(), std::logic_error);
+  SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
   // double registration
-  EXPECT_THROW([&vault_2]() {
-                 Singleton<Watchdog> watchdog_singleton(
-                     nullptr, nullptr, &vault_2);
-               }(),
-               std::logic_error);
-  vault_2.destroyInstances();
+  EXPECT_THROW([]() {
+      SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
+    }(),
+    std::logic_error);
+  vault2.destroyInstances();
   // double registration after destroy
-  EXPECT_THROW([&vault_2]() {
-                 Singleton<Watchdog> watchdog_singleton(
-                     nullptr, nullptr, &vault_2);
-               }(),
-               std::logic_error);
+  EXPECT_THROW([]() {
+      SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
+    }(),
+    std::logic_error);
 }
 
+struct SharedPtrUsageTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
+
 TEST(Singleton, SharedPtrUsage) {
-  SingletonVault vault;
+  auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
 
   EXPECT_EQ(vault.registeredSingletonCount(), 0);
-  Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
+  SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 1);
 
-  Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
+  SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
   EXPECT_EQ(vault.registeredSingletonCount(), 2);
 
   struct ATag {};
-  Singleton<Watchdog, ATag> named_watchdog_singleton(nullptr, nullptr, &vault);
+  SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
   vault.registrationComplete();
 
-  Watchdog* s1 = Singleton<Watchdog>::get(&vault);
+  Watchdog* s1 = SingletonSharedPtrUsage<Watchdog>::get();
   EXPECT_NE(s1, nullptr);
 
-  Watchdog* s2 = Singleton<Watchdog>::get(&vault);
+  Watchdog* s2 = SingletonSharedPtrUsage<Watchdog>::get();
   EXPECT_NE(s2, nullptr);
 
   EXPECT_EQ(s1, s2);
 
-  auto weak_s1 = Singleton<Watchdog>::get_weak(&vault);
+  auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
   auto shared_s1 = weak_s1.lock();
   EXPECT_EQ(shared_s1.get(), s1);
   EXPECT_EQ(shared_s1.use_count(), 2);
 
   {
-    auto named_weak_s1 = Singleton<Watchdog, ATag>::get_weak(&vault);
+    auto named_weak_s1 =
+      SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
     auto locked = named_weak_s1.lock();
     EXPECT_NE(locked.get(), shared_s1.get());
   }
@@ -268,16 +291,16 @@ TEST(Singleton, SharedPtrUsage) {
   locked_s1 = weak_s1.lock();
   EXPECT_TRUE(weak_s1.expired());
 
-  auto empty_s1 = Singleton<Watchdog>::get_weak(&vault);
+  auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
   EXPECT_FALSE(empty_s1.lock());
 
   vault.reenableInstances();
 
   // Singleton should be re-created only after reenableInstances() was called.
-  Watchdog* new_s1 = Singleton<Watchdog>::get(&vault);
+  Watchdog* new_s1 = SingletonSharedPtrUsage<Watchdog>::get();
   EXPECT_NE(new_s1->serial_number, old_serial);
 
-  auto new_s1_weak = Singleton<Watchdog>::get_weak(&vault);
+  auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
   auto new_s1_shared = new_s1_weak.lock();
   std::thread t([new_s1_shared]() mutable {
       std::this_thread::sleep_for(std::chrono::seconds{2});
@@ -298,43 +321,51 @@ TEST(Singleton, SharedPtrUsage) {
 // Some classes to test singleton dependencies.  NeedySingleton has a
 // dependency on NeededSingleton, which happens during its
 // construction.
-SingletonVault needy_vault;
+struct NeedyTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
 
 struct NeededSingleton {};
 struct NeedySingleton {
   NeedySingleton() {
-    auto unused = Singleton<NeededSingleton>::get(&needy_vault);
+    auto unused = SingletonNeedy<NeededSingleton>::get();
     EXPECT_NE(unused, nullptr);
   }
 };
 
 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
-SingletonVault self_needy_vault;
+struct SelfNeedyTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
+
 struct SelfNeedySingleton {
   SelfNeedySingleton() {
-    auto unused = Singleton<SelfNeedySingleton>::get(&self_needy_vault);
+    auto unused = SingletonSelfNeedy<SelfNeedySingleton>::get();
     EXPECT_NE(unused, nullptr);
   }
 };
 
 TEST(Singleton, SingletonDependencies) {
-  Singleton<NeededSingleton> needed_singleton(nullptr, nullptr, &needy_vault);
-  Singleton<NeedySingleton> needy_singleton(nullptr, nullptr, &needy_vault);
+  SingletonNeedy<NeededSingleton> needed_singleton;
+  SingletonNeedy<NeedySingleton> needy_singleton;
+  auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
+
   needy_vault.registrationComplete();
 
   EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
   EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
 
-  auto needy = Singleton<NeedySingleton>::get(&needy_vault);
+  auto needy = SingletonNeedy<NeedySingleton>::get();
   EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
 
-  Singleton<SelfNeedySingleton> self_needy_singleton(
-      nullptr, nullptr, &self_needy_vault);
+  SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
+  auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
+
   self_needy_vault.registrationComplete();
   EXPECT_THROW([]() {
-                 Singleton<SelfNeedySingleton>::get(&self_needy_vault);
-               }(),
-               std::out_of_range);
+      SingletonSelfNeedy<SelfNeedySingleton>::get();
+    }(),
+    std::out_of_range);
 }
 
 // A test to ensure multiple threads contending on singleton creation
@@ -345,17 +376,21 @@ class Slowpoke : public Watchdog {
   Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
 };
 
+struct ConcurrencyTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
+
 TEST(Singleton, SingletonConcurrency) {
-  SingletonVault vault;
-  Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
+  auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
+  SingletonConcurrency<Slowpoke> slowpoke_singleton;
   vault.registrationComplete();
 
   std::mutex gatekeeper;
   gatekeeper.lock();
-  auto func = [&vault, &gatekeeper]() {
+  auto func = [&gatekeeper]() {
     gatekeeper.lock();
     gatekeeper.unlock();
-    auto unused = Singleton<Slowpoke>::get(&vault);
+    auto unused = SingletonConcurrency<Slowpoke>::get();
   };
 
   EXPECT_EQ(vault.livingSingletonCount(), 0);
@@ -373,14 +408,18 @@ TEST(Singleton, SingletonConcurrency) {
   EXPECT_EQ(vault.livingSingletonCount(), 1);
 }
 
+struct ConcurrencyStressTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
+
 TEST(Singleton, SingletonConcurrencyStress) {
-  SingletonVault vault;
-  Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
+  auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
+  SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
 
   std::vector<std::thread> ts;
   for (size_t i = 0; i < 100; ++i) {
     ts.emplace_back([&]() {
-        slowpoke_singleton.get_weak(&vault).lock();
+        slowpoke_singleton.get_weak().lock();
       });
   }
 
@@ -412,23 +451,28 @@ int* getNormalSingleton() {
   return &normal_singleton_value;
 }
 
+struct MockTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonMock = Singleton <T, Tag, MockTag>;
+
 // Verify that existing Singleton's can be overridden
 // using the make_mock functionality.
-TEST(Singleton, make_mock) {
-  SingletonVault vault(SingletonVault::Type::Strict);
-  Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
+TEST(Singleton, MockTest) {
+  auto& vault = *SingletonVault::singleton<MockTag>();
+
+  SingletonMock<Watchdog> watchdog_singleton;
   vault.registrationComplete();
 
   // Registring singletons after registrationComplete called works
   // with make_mock (but not with Singleton ctor).
   EXPECT_EQ(vault.registeredSingletonCount(), 1);
-  int serial_count_first = Singleton<Watchdog>::get(&vault)->serial_number;
+  int serial_count_first = SingletonMock<Watchdog>::get()->serial_number;
 
   // Override existing mock using make_mock.
-  Singleton<Watchdog>::make_mock(nullptr, nullptr, &vault);
+  SingletonMock<Watchdog>::make_mock();
 
   EXPECT_EQ(vault.registeredSingletonCount(), 1);
-  int serial_count_mock = Singleton<Watchdog>::get(&vault)->serial_number;
+  int serial_count_mock = SingletonMock<Watchdog>::get()->serial_number;
 
   // If serial_count value is the same, then singleton was not replaced.
   EXPECT_NE(serial_count_first, serial_count_mock);
@@ -450,34 +494,25 @@ BENCHMARK_RELATIVE(MeyersSingleton, n) {
   }
 }
 
-BENCHMARK_RELATIVE(FollySingletonSlow, n) {
-  SingletonVault benchmark_vault;
-  Singleton<BenchmarkSingleton> benchmark_singleton(
-      nullptr, nullptr, &benchmark_vault);
-  benchmark_vault.registrationComplete();
+struct BenchmarkTag {};
+template <typename T, typename Tag = detail::DefaultTag>
+using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
+
+SingletonBenchmark<BenchmarkSingleton> benchmark_singleton;
 
+BENCHMARK_RELATIVE(FollySingletonSlow, n) {
   for (size_t i = 0; i < n; ++i) {
-    doNotOptimizeAway(Singleton<BenchmarkSingleton>::get(&benchmark_vault));
+    doNotOptimizeAway(SingletonBenchmark<BenchmarkSingleton>::get());
   }
 }
 
 BENCHMARK_RELATIVE(FollySingletonFast, n) {
-  SingletonVault benchmark_vault;
-  Singleton<BenchmarkSingleton> benchmark_singleton(
-      nullptr, nullptr, &benchmark_vault);
-  benchmark_vault.registrationComplete();
-
   for (size_t i = 0; i < n; ++i) {
     doNotOptimizeAway(benchmark_singleton.get_fast());
   }
 }
 
 BENCHMARK_RELATIVE(FollySingletonFastWeak, n) {
-  SingletonVault benchmark_vault;
-  Singleton<BenchmarkSingleton> benchmark_singleton(
-      nullptr, nullptr, &benchmark_vault);
-  benchmark_vault.registrationComplete();
-
   for (size_t i = 0; i < n; ++i) {
     benchmark_singleton.get_weak_fast();
   }
index e87ff622763069abca647920bc111d7ed77cc79c..4fcc1eaee14fd40bfddfa693b685d13abe73d6a8 100644 (file)
@@ -40,12 +40,16 @@ TEST(SingletonVault, singletonReturnsSingletonInstance) {
   EXPECT_EQ(c, cpp);
 }
 
+struct TestTag {};
+template <typename T, typename Tag = folly::detail::DefaultTag>
+using SingletonTest = folly::Singleton <T, Tag, TestTag>;
+
 TEST(SingletonVault, singletonsAreCreatedAndDestroyed) {
-  auto *vault = new folly::SingletonVault();
-  folly::Singleton<InstanceCounter> counter_singleton(nullptr, nullptr, vault);
+  auto vault = folly::SingletonVault::singleton<TestTag>();
+  SingletonTest<InstanceCounter> counter_singleton;
   SingletonVault_registrationComplete((SingletonVault_t*) vault);
-  InstanceCounter *counter = folly::Singleton<InstanceCounter>::get(vault);
+  InstanceCounter *counter = SingletonTest<InstanceCounter>::get();
   EXPECT_EQ(instance_counter_instances, 1);
-  delete vault;
+  SingletonVault_destroyInstances((SingletonVault_t*) vault);
   EXPECT_EQ(instance_counter_instances, 0);
 }