From: Andrii Grynenko Date: Wed, 18 Feb 2015 01:03:58 +0000 (-0800) Subject: Kill get_fast/get_weak_fast Singletonn API X-Git-Tag: v0.27.0~33 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5d1db31bc0a281d695a1366b3193566c3476968c;p=folly.git Kill get_fast/get_weak_fast Singletonn API 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 --- diff --git a/folly/experimental/Singleton.h b/folly/experimental/Singleton.h index 6ad4d428..bff9405a 100644 --- a/folly/experimental/Singleton.h +++ b/folly/experimental/Singleton.h @@ -34,18 +34,9 @@ // std::weak_ptr instance = // Singleton::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 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 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 get_weak_fast() { - return entry_.get_weak(); - } - // Allow the Singleton 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(); - 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& entry_; }; } diff --git a/folly/experimental/test/SingletonTest.cpp b/folly/experimental/test/SingletonTest.cpp index 4ecda73d..f24ae655 100644 --- a/folly/experimental/test/SingletonTest.cpp +++ b/folly/experimental/test/SingletonTest.cpp @@ -139,9 +139,9 @@ TEST(Singleton, DirectUsage) { EXPECT_EQ(vault.registeredSingletonCount(), 2); vault.registrationComplete(); - EXPECT_NE(watchdog.ptr(), nullptr); - EXPECT_EQ(watchdog.ptr(), SingletonDirectUsage::get()); - EXPECT_NE(watchdog.ptr(), named_watchdog.ptr()); + EXPECT_NE(watchdog.get(), nullptr); + EXPECT_EQ(watchdog.get(), SingletonDirectUsage::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::get(); - EXPECT_EQ(s1, watchdog1_singleton.ptr()); + EXPECT_EQ(s1, watchdog1_singleton.get()); Watchdog* s2 = SingletonNamedUsage::get(); - EXPECT_EQ(s2, watchdog2_singleton.ptr()); + EXPECT_EQ(s2, watchdog2_singleton.get()); EXPECT_NE(s1, s2); Watchdog* s3 = SingletonNamedUsage::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::get(); - EXPECT_EQ(s4, watchdog3_singleton.ptr()); + EXPECT_EQ(s4, watchdog3_singleton.get()); vault.destroyInstances(); } @@ -499,23 +499,21 @@ struct BenchmarkTag {}; template using SingletonBenchmark = Singleton ; -SingletonBenchmark benchmark_singleton; +struct GetTag{}; +struct GetWeakTag{}; -BENCHMARK_RELATIVE(FollySingletonSlow, n) { - for (size_t i = 0; i < n; ++i) { - doNotOptimizeAway(SingletonBenchmark::get()); - } -} +SingletonBenchmark benchmark_singleton_get; +SingletonBenchmark 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::get()); } } -BENCHMARK_RELATIVE(FollySingletonFastWeak, n) { +BENCHMARK_RELATIVE(FollySingletonWeak, n) { for (size_t i = 0; i < n; ++i) { - benchmark_singleton.get_weak_fast(); + SingletonBenchmark::get_weak(); } } diff --git a/folly/futures/detail/ThreadWheelTimekeeper.cpp b/folly/futures/detail/ThreadWheelTimekeeper.cpp index 28ae72de..40eb7eef 100644 --- a/folly/futures/detail/ThreadWheelTimekeeper.cpp +++ b/folly/futures/detail/ThreadWheelTimekeeper.cpp @@ -87,7 +87,7 @@ Future ThreadWheelTimekeeper::after(Duration dur) { } Timekeeper* getTimekeeperSingleton() { - return timekeeperSingleton_.get_fast(); + return timekeeperSingleton_.get(); } }} // folly::detail diff --git a/folly/wangle/concurrent/GlobalExecutor.cpp b/folly/wangle/concurrent/GlobalExecutor.cpp index eb97f06d..fb0de13d 100644 --- a/folly/wangle/concurrent/GlobalExecutor.cpp +++ b/folly/wangle/concurrent/GlobalExecutor.cpp @@ -60,8 +60,8 @@ std::shared_ptr getExecutor( Singleton>& sDefaultExecutor, Singleton& sExecutorLock) { std::shared_ptr 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 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 executor, Singleton>& sExecutor, Singleton& 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 getCPUExecutor() {