Kill get_fast/get_weak_fast Singletonn API
authorAndrii Grynenko <andrii@fb.com>
Wed, 18 Feb 2015 01:03:58 +0000 (17:03 -0800)
committerAlecs King <int@fb.com>
Tue, 3 Mar 2015 03:22:40 +0000 (19:22 -0800)
Summary: After D1827390 regular get and get_weak is comparable to Meyers and static singletons, so there's no need to keey _fast APIs.

Test Plan: benchmark && fbmake

Reviewed By: mshneer@fb.com

Subscribers: trunkagent, configerator-diffs@, fbcode-common-diffs@, mcduff, hitesh, mshneer, fugalh, acampi, alikhtarov, folly-diffs@, jsedgwick, yfeldblum

FB internal diff: D1843219

Signature: t1:1843219:1424216566:f2f182a1c86bb5f0fb1f978d8c6b7a4388198f5f

folly/experimental/Singleton.h
folly/experimental/test/SingletonTest.cpp
folly/futures/detail/ThreadWheelTimekeeper.cpp
folly/wangle/concurrent/GlobalExecutor.cpp

index 6ad4d4286a1963d507eb61753c99c0208087d013..bff9405ae1296a35ee7e538432a81893e23d09d2 100644 (file)
 // std::weak_ptr<MyExpensiveService> instance =
 //     Singleton<MyExpensiveService>::get_weak();
 //
-// Within same compilation unit you should directly access it by the variable
-// defining the singleton via get_fast()/get_weak_fast(), and even treat that
-// variable like a smart pointer (dereferencing it or using the -> operator):
-//
-// MyExpensiveService* instance = the_singleton.get_fast();
-// or
-// std::weak_ptr<MyExpensiveService> instance = the_singleton.get_weak_fast();
-// or even
-// the_singleton->doSomething();
-//
-// *_fast() accessors are faster than static accessors, and have performance
-// similar to Meyers singletons/static objects.
+// You also can directly access it by the variable defining the
+// singleton rather than via get(), and even treat that variable like
+// a smart pointer (dereferencing it or using the -> operator).
 //
 // Please note, however, that all non-weak_ptr interfaces are
 // inherently subject to races with destruction.  Use responsibly.
@@ -67,9 +58,9 @@
 // folly::Singleton<MyExpensiveService, Tag2> s2();
 // }
 // ...
-// MyExpensiveService* svc_default = s_default.get_fast();
-// MyExpensiveService* svc1 = s1.get_fast();
-// MyExpensiveService* svc2 = s2.get_fast();
+// MyExpensiveService* svc_default = s_default.get();
+// MyExpensiveService* svc1 = s1.get();
+// MyExpensiveService* svc2 = s2.get();
 //
 // By default, the singleton instance is constructed via new and
 // deleted via delete, but this is configurable:
@@ -448,12 +439,6 @@ class Singleton {
     return getEntry().get();
   }
 
-  // Same as get, but should be preffered to it in the same compilation
-  // unit, where Singleton is registered.
-  T* get_fast() {
-    return entry_.get();
-  }
-
   // If, however, you do need to hold a reference to the specific
   // 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
@@ -462,17 +447,10 @@ class Singleton {
     return getEntry().get_weak();
   }
 
-  // Same as get_weak, but should be preffered to it in the same compilation
-  // unit, where Singleton is registered.
-  std::weak_ptr<T> get_weak_fast() {
-    return entry_.get_weak();
-  }
-
   // Allow the Singleton<t> instance to also retrieve the underlying
   // singleton, if desired.
-  T* ptr() { return get_fast(); }
-  T& operator*() { return *ptr(); }
-  T* operator->() { return ptr(); }
+  T& operator*() { return *get(); }
+  T* operator->() { return get(); }
 
   explicit Singleton(std::nullptr_t _ = nullptr,
                      Singleton::TeardownFunc t = nullptr) :
@@ -480,15 +458,15 @@ class Singleton {
   }
 
   explicit Singleton(Singleton::CreateFunc c,
-                     Singleton::TeardownFunc t = nullptr) : entry_(getEntry()) {
+                     Singleton::TeardownFunc t = nullptr) {
     if (c == nullptr) {
       throw std::logic_error(
         "nullptr_t should be passed if you want T to be default constructed");
     }
 
     auto vault = SingletonVault::singleton<VaultTag>();
-    entry_.registerSingleton(std::move(c), getTeardownFunc(std::move(t)));
-    vault->registerSingleton(&entry_);
+    getEntry().registerSingleton(std::move(c), getTeardownFunc(std::move(t)));
+    vault->registerSingleton(&getEntry());
   }
 
   /**
@@ -532,12 +510,6 @@ class Singleton {
       return t;
     }
   }
-
-  // This is pointing to SingletonHolder paired with this singleton object. This
-  // is never reset, so each SingletonHolder should never be destroyed.
-  // 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::SingletonHolder<T>& entry_;
 };
 
 }
index 4ecda73d4804fad5a3f9a7c0bacb9a459685104b..f24ae655b7989f45a495bb00caf439ff12408cc6 100644 (file)
@@ -139,9 +139,9 @@ TEST(Singleton, DirectUsage) {
   EXPECT_EQ(vault.registeredSingletonCount(), 2);
   vault.registrationComplete();
 
-  EXPECT_NE(watchdog.ptr(), nullptr);
-  EXPECT_EQ(watchdog.ptr(), SingletonDirectUsage<Watchdog>::get());
-  EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
+  EXPECT_NE(watchdog.get(), nullptr);
+  EXPECT_EQ(watchdog.get(), SingletonDirectUsage<Watchdog>::get());
+  EXPECT_NE(watchdog.get(), named_watchdog.get());
   EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
   EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
 
@@ -172,19 +172,19 @@ TEST(Singleton, NamedUsage) {
 
   // Verify our three singletons are distinct and non-nullptr.
   Watchdog* s1 = SingletonNamedUsage<Watchdog, Watchdog1>::get();
-  EXPECT_EQ(s1, watchdog1_singleton.ptr());
+  EXPECT_EQ(s1, watchdog1_singleton.get());
   Watchdog* s2 = SingletonNamedUsage<Watchdog, Watchdog2>::get();
-  EXPECT_EQ(s2, watchdog2_singleton.ptr());
+  EXPECT_EQ(s2, watchdog2_singleton.get());
   EXPECT_NE(s1, s2);
   Watchdog* s3 = SingletonNamedUsage<Watchdog, Watchdog3>::get();
-  EXPECT_EQ(s3, watchdog3_singleton.ptr());
+  EXPECT_EQ(s3, watchdog3_singleton.get());
   EXPECT_NE(s3, s1);
   EXPECT_NE(s3, s2);
 
   // Verify the "default" singleton is the same as the DefaultTag-tagged
   // singleton.
   Watchdog* s4 = SingletonNamedUsage<Watchdog>::get();
-  EXPECT_EQ(s4, watchdog3_singleton.ptr());
+  EXPECT_EQ(s4, watchdog3_singleton.get());
 
   vault.destroyInstances();
 }
@@ -499,23 +499,21 @@ struct BenchmarkTag {};
 template <typename T, typename Tag = detail::DefaultTag>
 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
 
-SingletonBenchmark<BenchmarkSingleton> benchmark_singleton;
+struct GetTag{};
+struct GetWeakTag{};
 
-BENCHMARK_RELATIVE(FollySingletonSlow, n) {
-  for (size_t i = 0; i < n; ++i) {
-    doNotOptimizeAway(SingletonBenchmark<BenchmarkSingleton>::get());
-  }
-}
+SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
+SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
 
-BENCHMARK_RELATIVE(FollySingletonFast, n) {
+BENCHMARK_RELATIVE(FollySingleton, n) {
   for (size_t i = 0; i < n; ++i) {
-    doNotOptimizeAway(benchmark_singleton.get_fast());
+    doNotOptimizeAway(SingletonBenchmark<BenchmarkSingleton, GetTag>::get());
   }
 }
 
-BENCHMARK_RELATIVE(FollySingletonFastWeak, n) {
+BENCHMARK_RELATIVE(FollySingletonWeak, n) {
   for (size_t i = 0; i < n; ++i) {
-    benchmark_singleton.get_weak_fast();
+    SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
   }
 }
 
index 28ae72de40f460ce23ec598d9ca2d096bdb0f435..40eb7eefe564099bef5bff11689cd49da6099d4a 100644 (file)
@@ -87,7 +87,7 @@ Future<void> ThreadWheelTimekeeper::after(Duration dur) {
 }
 
 Timekeeper* getTimekeeperSingleton() {
-  return timekeeperSingleton_.get_fast();
+  return timekeeperSingleton_.get();
 }
 
 }} // folly::detail
index eb97f06dde252edffece337c996360fb153bb329..fb0de13dd1e489e72536ae89be9a06e6c60e21c0 100644 (file)
@@ -60,8 +60,8 @@ std::shared_ptr<Exe> getExecutor(
     Singleton<std::shared_ptr<DefaultExe>>& sDefaultExecutor,
     Singleton<RWSpinLock, LockTag>& sExecutorLock) {
   std::shared_ptr<Exe> executor;
-  auto singleton = sExecutor.get_fast();
-  auto lock = sExecutorLock.get_fast();
+  auto singleton = sExecutor.get();
+  auto lock = sExecutorLock.get();
 
   {
     RWSpinLock::ReadHolder guard(lock);
@@ -74,7 +74,7 @@ std::shared_ptr<Exe> getExecutor(
   RWSpinLock::WriteHolder guard(lock);
   executor = singleton->lock();
   if (!executor) {
-    executor = *sDefaultExecutor.get_fast();
+    executor = *sDefaultExecutor.get();
     *singleton = executor;
   }
   return executor;
@@ -85,8 +85,8 @@ void setExecutor(
     std::shared_ptr<Exe> executor,
     Singleton<std::weak_ptr<Exe>>& sExecutor,
     Singleton<RWSpinLock, LockTag>& sExecutorLock) {
-  RWSpinLock::WriteHolder guard(sExecutorLock.get_fast());
-  *sExecutor.get_fast() = std::move(executor);
+  RWSpinLock::WriteHolder guard(sExecutorLock.get());
+  *sExecutor.get() = std::move(executor);
 }
 
 std::shared_ptr<Executor> getCPUExecutor() {