2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/Singleton.h>
20 #include <folly/io/async/EventBase.h>
22 #include <folly/Benchmark.h>
24 #include <glog/logging.h>
25 #include <gtest/gtest.h>
26 #include <boost/thread/barrier.hpp>
28 using namespace folly;
30 // A simple class that tracks how often instances of the class and
31 // subclasses are created, and the ordering. Also tracks a global
32 // unique counter for each object.
33 std::atomic<size_t> global_counter(19770326);
35 static std::vector<Watchdog*> creation_order;
36 Watchdog() : serial_number(++global_counter) {
37 creation_order.push_back(this);
41 if (creation_order.back() != this) {
42 throw std::out_of_range("Watchdog destruction order mismatch");
44 creation_order.pop_back();
47 const size_t serial_number;
48 size_t livingWatchdogCount() const { return creation_order.size(); }
50 Watchdog(const Watchdog&) = delete;
51 Watchdog& operator=(const Watchdog&) = delete;
52 Watchdog(Watchdog&&) noexcept = default;
55 std::vector<Watchdog*> Watchdog::creation_order;
57 // Some basic types we use for tracking.
58 struct ChildWatchdog : public Watchdog {};
59 struct GlobalWatchdog : public Watchdog {};
60 struct UnregisteredWatchdog : public Watchdog {};
63 Singleton<GlobalWatchdog> global_watchdog;
66 // Test basic global usage (the default way singletons will generally
68 TEST(Singleton, BasicGlobalUsage) {
69 EXPECT_EQ(Watchdog::creation_order.size(), 0);
70 EXPECT_EQ(SingletonVault::singleton()->registeredSingletonCount(), 1);
71 EXPECT_EQ(SingletonVault::singleton()->livingSingletonCount(), 0);
74 std::shared_ptr<GlobalWatchdog> wd1 = Singleton<GlobalWatchdog>::try_get();
75 EXPECT_NE(wd1, nullptr);
76 EXPECT_EQ(Watchdog::creation_order.size(), 1);
77 std::shared_ptr<GlobalWatchdog> wd2 = Singleton<GlobalWatchdog>::try_get();
78 EXPECT_NE(wd2, nullptr);
79 EXPECT_EQ(wd1.get(), wd2.get());
80 EXPECT_EQ(Watchdog::creation_order.size(), 1);
83 SingletonVault::singleton()->destroyInstances();
84 EXPECT_EQ(Watchdog::creation_order.size(), 0);
87 TEST(Singleton, MissingSingleton) {
88 EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
92 struct BasicUsageTag {};
93 template <typename T, typename Tag = detail::DefaultTag>
94 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
96 // Exercise some basic codepaths ensuring registration order and
97 // destruction order happen as expected, that instances are created
98 // when expected, etc etc.
99 TEST(Singleton, BasicUsage) {
100 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
102 EXPECT_EQ(vault.registeredSingletonCount(), 0);
103 SingletonBasicUsage<Watchdog> watchdog_singleton;
104 EXPECT_EQ(vault.registeredSingletonCount(), 1);
106 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
107 EXPECT_EQ(vault.registeredSingletonCount(), 2);
109 vault.registrationComplete();
111 // limit a scope to release references so we can destroy them later
113 std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
114 EXPECT_NE(s1, nullptr);
116 std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
117 EXPECT_NE(s2, nullptr);
121 std::shared_ptr<ChildWatchdog> s3 =
122 SingletonBasicUsage<ChildWatchdog>::try_get();
123 EXPECT_NE(s3, nullptr);
126 EXPECT_EQ(vault.registeredSingletonCount(), 2);
127 EXPECT_EQ(vault.livingSingletonCount(), 2);
130 vault.destroyInstances();
131 EXPECT_EQ(vault.registeredSingletonCount(), 2);
132 EXPECT_EQ(vault.livingSingletonCount(), 0);
135 struct DirectUsageTag {};
136 template <typename T, typename Tag = detail::DefaultTag>
137 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
139 TEST(Singleton, DirectUsage) {
140 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
142 EXPECT_EQ(vault.registeredSingletonCount(), 0);
144 // Verify we can get to the underlying singletons via directly using
145 // the singleton definition.
146 SingletonDirectUsage<Watchdog> watchdog;
148 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
149 EXPECT_EQ(vault.registeredSingletonCount(), 2);
150 vault.registrationComplete();
152 EXPECT_NE(watchdog.try_get(), nullptr);
153 EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
154 EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
155 EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
157 vault.destroyInstances();
160 struct NamedUsageTag {};
161 template <typename T, typename Tag = detail::DefaultTag>
162 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
164 TEST(Singleton, NamedUsage) {
165 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
167 EXPECT_EQ(vault.registeredSingletonCount(), 0);
169 // Define two named Watchdog singletons and one unnamed singleton.
172 typedef detail::DefaultTag Watchdog3;
173 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
174 EXPECT_EQ(vault.registeredSingletonCount(), 1);
175 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
176 EXPECT_EQ(vault.registeredSingletonCount(), 2);
177 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
178 EXPECT_EQ(vault.registeredSingletonCount(), 3);
180 vault.registrationComplete();
182 // Verify our three singletons are distinct and non-nullptr.
183 auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
184 EXPECT_EQ(s1, watchdog1_singleton.try_get());
185 auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
186 EXPECT_EQ(s2, watchdog2_singleton.try_get());
188 auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
189 EXPECT_EQ(s3, watchdog3_singleton.try_get());
193 // Verify the "default" singleton is the same as the DefaultTag-tagged
195 auto s4 = SingletonNamedUsage<Watchdog>::try_get();
196 EXPECT_EQ(s4, watchdog3_singleton.try_get());
199 vault.destroyInstances();
202 struct NaughtyUsageTag {};
203 template <typename T, typename Tag = detail::DefaultTag>
204 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
205 struct NaughtyUsageTag2 {};
206 template <typename T, typename Tag = detail::DefaultTag>
207 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
209 // Some pathological cases such as getting unregistered singletons,
210 // double registration, etc.
211 TEST(Singleton, NaughtyUsage) {
212 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
214 vault.registrationComplete();
217 EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
218 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
220 vault.destroyInstances();
222 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
224 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
225 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
227 // double registration
228 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
230 vault2.destroyInstances();
232 // double registration after destroy
233 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
237 struct SharedPtrUsageTag {};
238 template <typename T, typename Tag = detail::DefaultTag>
239 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
241 // TODO (anob): revisit this test
242 TEST(Singleton, SharedPtrUsage) {
243 struct WatchdogHolder {
246 LOG(ERROR) << "The following log message with stack trace is expected";
250 std::shared_ptr<Watchdog> watchdog;
253 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
255 EXPECT_EQ(vault.registeredSingletonCount(), 0);
256 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
257 EXPECT_EQ(vault.registeredSingletonCount(), 1);
259 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
260 EXPECT_EQ(vault.registeredSingletonCount(), 2);
263 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
265 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
267 vault.registrationComplete();
269 // Initilize holder singleton first, so that it's the last one to be
271 watchdog_holder_singleton.try_get();
273 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
274 EXPECT_NE(s1, nullptr);
276 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
277 EXPECT_NE(s2, nullptr);
281 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
283 auto shared_s1 = weak_s1.lock();
284 EXPECT_EQ(shared_s1.get(), s1);
285 EXPECT_EQ(shared_s1.use_count(), 2);
287 auto old_serial = shared_s1->serial_number;
291 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
292 auto locked = named_weak_s1.lock();
293 EXPECT_NE(locked.get(), shared_s1.get());
296 // We should release externally locked shared_ptr, otherwise it will be
298 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
300 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
302 auto start_time = std::chrono::steady_clock::now();
303 vault.destroyInstances();
304 auto duration = std::chrono::steady_clock::now() - start_time;
305 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
306 duration < std::chrono::seconds{6});
308 EXPECT_EQ(vault.registeredSingletonCount(), 4);
309 EXPECT_EQ(vault.livingSingletonCount(), 0);
311 EXPECT_TRUE(weak_s1.expired());
313 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
314 EXPECT_FALSE(empty_s1.lock());
316 vault.reenableInstances();
319 // Singleton should be re-created only after reenableInstances() was called.
320 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
321 // Track serial number rather than pointer since the memory could be
322 // re-used when we create new_s1.
323 EXPECT_NE(new_s1->serial_number, old_serial);
326 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
327 auto new_s1_shared = new_s1_weak.lock();
328 std::thread t([new_s1_shared]() mutable {
329 std::this_thread::sleep_for(std::chrono::seconds{2});
330 new_s1_shared.reset();
332 new_s1_shared.reset();
334 auto start_time = std::chrono::steady_clock::now();
335 vault.destroyInstances();
336 auto duration = std::chrono::steady_clock::now() - start_time;
337 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
338 duration < std::chrono::seconds{3});
340 EXPECT_TRUE(new_s1_weak.expired());
344 // Some classes to test singleton dependencies. NeedySingleton has a
345 // dependency on NeededSingleton, which happens during its
348 template <typename T, typename Tag = detail::DefaultTag>
349 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
351 struct NeededSingleton {};
352 struct NeedySingleton {
354 auto unused = SingletonNeedy<NeededSingleton>::try_get();
355 EXPECT_NE(unused, nullptr);
359 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
360 struct SelfNeedyTag {};
361 template <typename T, typename Tag = detail::DefaultTag>
362 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
364 struct SelfNeedySingleton {
365 SelfNeedySingleton() {
366 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
367 EXPECT_NE(unused, nullptr);
371 TEST(Singleton, SingletonDependencies) {
372 SingletonNeedy<NeededSingleton> needed_singleton;
373 SingletonNeedy<NeedySingleton> needy_singleton;
374 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
376 needy_vault.registrationComplete();
378 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
379 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
381 auto needy = SingletonNeedy<NeedySingleton>::try_get();
382 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
384 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
385 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
387 self_needy_vault.registrationComplete();
388 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
392 // A test to ensure multiple threads contending on singleton creation
393 // properly wait for creation rather than thinking it is a circular
395 class Slowpoke : public Watchdog {
397 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
400 struct ConcurrencyTag {};
401 template <typename T, typename Tag = detail::DefaultTag>
402 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
404 TEST(Singleton, SingletonConcurrency) {
405 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
406 SingletonConcurrency<Slowpoke> slowpoke_singleton;
407 vault.registrationComplete();
409 std::mutex gatekeeper;
411 auto func = [&gatekeeper]() {
414 auto unused = SingletonConcurrency<Slowpoke>::try_get();
417 EXPECT_EQ(vault.livingSingletonCount(), 0);
418 std::vector<std::thread> threads;
419 for (int i = 0; i < 100; ++i) {
420 threads.emplace_back(func);
422 // If circular dependency checks fail, the unlock would trigger a
423 // crash. Instead, it succeeds, and we have exactly one living
426 for (auto& t : threads) {
429 EXPECT_EQ(vault.livingSingletonCount(), 1);
432 struct ErrorConstructor {
433 static size_t constructCount_;
435 if ((constructCount_++) == 0) {
436 throw std::runtime_error("first time fails");
440 size_t ErrorConstructor::constructCount_(0);
442 struct CreationErrorTag {};
443 template <typename T, typename Tag = detail::DefaultTag>
444 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
446 TEST(Singleton, SingletonCreationError) {
447 auto& vault = *SingletonVault::singleton<CreationErrorTag>();
448 SingletonCreationError<ErrorConstructor> error_once_singleton;
450 // first time should error out
451 EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
453 // second time it'll work fine
454 error_once_singleton.get_weak().lock();
458 struct ConcurrencyStressTag {};
459 template <typename T, typename Tag = detail::DefaultTag>
460 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
462 TEST(Singleton, SingletonConcurrencyStress) {
463 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
464 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
466 std::vector<std::thread> ts;
467 for (size_t i = 0; i < 100; ++i) {
468 ts.emplace_back([&]() {
469 slowpoke_singleton.get_weak().lock();
473 for (size_t i = 0; i < 100; ++i) {
474 std::chrono::milliseconds d(20);
476 std::this_thread::sleep_for(d);
477 vault.destroyInstances();
478 std::this_thread::sleep_for(d);
479 vault.destroyInstances();
488 struct EagerInitSyncTag {};
490 template <typename T, typename Tag = detail::DefaultTag>
491 using SingletonEagerInitSync = Singleton<T, Tag, EagerInitSyncTag>;
492 TEST(Singleton, SingletonEagerInitSync) {
493 auto& vault = *SingletonVault::singleton<EagerInitSyncTag>();
494 bool didEagerInit = false;
495 auto sing = SingletonEagerInitSync<std::string>(
496 [&] {didEagerInit = true; return new std::string("foo"); })
498 vault.registrationComplete();
499 EXPECT_TRUE(didEagerInit);
500 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
504 struct EagerInitAsyncTag {};
506 template <typename T, typename Tag = detail::DefaultTag>
507 using SingletonEagerInitAsync = Singleton<T, Tag, EagerInitAsyncTag>;
508 TEST(Singleton, SingletonEagerInitAsync) {
509 auto& vault = *SingletonVault::singleton<EagerInitAsyncTag>();
510 bool didEagerInit = false;
511 auto sing = SingletonEagerInitAsync<std::string>(
512 [&] {didEagerInit = true; return new std::string("foo"); })
515 vault.setEagerInitExecutor(&eb);
516 vault.registrationComplete();
517 EXPECT_FALSE(didEagerInit);
519 EXPECT_TRUE(didEagerInit);
520 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
524 class TestEagerInitParallelExecutor : public folly::Executor {
526 explicit TestEagerInitParallelExecutor(const size_t threadCount) {
527 eventBases_.reserve(threadCount);
528 threads_.reserve(threadCount);
529 for (size_t i = 0; i < threadCount; i++) {
530 eventBases_.push_back(std::make_shared<folly::EventBase>());
531 auto eb = eventBases_.back();
532 threads_.emplace_back(std::make_shared<std::thread>(
533 [eb] { eb->loopForever(); }));
537 virtual ~TestEagerInitParallelExecutor() override {
538 for (auto eb : eventBases_) {
539 eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
541 for (auto thread : threads_) {
546 virtual void add(folly::Func func) override {
547 const auto index = (counter_ ++) % eventBases_.size();
548 eventBases_[index]->add(func);
552 std::vector<std::shared_ptr<folly::EventBase>> eventBases_;
553 std::vector<std::shared_ptr<std::thread>> threads_;
554 std::atomic<size_t> counter_ {0};
559 struct EagerInitParallelTag {};
561 template <typename T, typename Tag = detail::DefaultTag>
562 using SingletonEagerInitParallel = Singleton<T, Tag, EagerInitParallelTag>;
563 TEST(Singleton, SingletonEagerInitParallel) {
564 const static size_t kIters = 1000;
565 const static size_t kThreads = 20;
567 std::atomic<size_t> initCounter;
569 auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
571 auto sing = SingletonEagerInitParallel<std::string>(
572 [&] {++initCounter; return new std::string(""); })
575 for (size_t i = 0; i < kIters; i++) {
577 // clean up each time
578 vault.destroyInstances();
579 vault.reenableInstances();
582 initCounter.store(0);
585 boost::barrier barrier(kThreads + 1);
586 TestEagerInitParallelExecutor exe(kThreads);
587 vault.setEagerInitExecutor(&exe);
588 vault.registrationComplete(false);
590 EXPECT_EQ(0, initCounter.load());
592 for (size_t j = 0; j < kThreads; j++) {
595 vault.startEagerInit();
600 barrier.wait(); // to await all threads' readiness
601 barrier.wait(); // to await all threads' completion
604 EXPECT_EQ(1, initCounter.load());
606 sing.get_weak(); // (avoid compile error complaining about unused var)
610 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
611 // singleton. Meyers are insanely fast, but (hopefully) Folly
612 // singletons are fast "enough."
613 int* getMeyersSingleton() {
614 static auto ret = new int(0);
618 int normal_singleton_value = 0;
619 int* getNormalSingleton() {
620 doNotOptimizeAway(&normal_singleton_value);
621 return &normal_singleton_value;
625 template <typename T, typename Tag = detail::DefaultTag>
626 using SingletonMock = Singleton <T, Tag, MockTag>;
628 // Verify that existing Singleton's can be overridden
629 // using the make_mock functionality.
630 TEST(Singleton, MockTest) {
631 auto& vault = *SingletonVault::singleton<MockTag>();
633 SingletonMock<Watchdog> watchdog_singleton;
634 vault.registrationComplete();
636 // Registring singletons after registrationComplete called works
637 // with make_mock (but not with Singleton ctor).
638 EXPECT_EQ(vault.registeredSingletonCount(), 1);
639 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
641 // Override existing mock using make_mock.
642 SingletonMock<Watchdog>::make_mock();
644 EXPECT_EQ(vault.registeredSingletonCount(), 1);
645 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
647 // If serial_count value is the same, then singleton was not replaced.
648 EXPECT_NE(serial_count_first, serial_count_mock);
651 struct BenchmarkSingleton {
655 BENCHMARK(NormalSingleton, n) {
656 for (size_t i = 0; i < n; ++i) {
657 doNotOptimizeAway(getNormalSingleton());
661 BENCHMARK_RELATIVE(MeyersSingleton, n) {
662 for (size_t i = 0; i < n; ++i) {
663 doNotOptimizeAway(getMeyersSingleton());
667 struct BenchmarkTag {};
668 template <typename T, typename Tag = detail::DefaultTag>
669 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
674 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
675 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
677 BENCHMARK_RELATIVE(FollySingleton, n) {
678 for (size_t i = 0; i < n; ++i) {
679 SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
683 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
684 for (size_t i = 0; i < n; ++i) {
685 SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
689 int main(int argc, char* argv[]) {
690 testing::InitGoogleTest(&argc, argv);
691 google::InitGoogleLogging(argv[0]);
692 gflags::ParseCommandLineFlags(&argc, &argv, true);
694 SingletonVault::singleton()->registrationComplete();
696 auto ret = RUN_ALL_TESTS();
698 folly::runBenchmarksOnFlag();