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>
21 #include <folly/test/SingletonTestStructs.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 TEST(Singleton, MissingSingleton) {
31 EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
35 struct BasicUsageTag {};
36 template <typename T, typename Tag = detail::DefaultTag>
37 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
39 // Exercise some basic codepaths ensuring registration order and
40 // destruction order happen as expected, that instances are created
41 // when expected, etc etc.
42 TEST(Singleton, BasicUsage) {
43 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
45 EXPECT_EQ(vault.registeredSingletonCount(), 0);
46 SingletonBasicUsage<Watchdog> watchdog_singleton;
47 EXPECT_EQ(vault.registeredSingletonCount(), 1);
49 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
50 EXPECT_EQ(vault.registeredSingletonCount(), 2);
52 vault.registrationComplete();
54 // limit a scope to release references so we can destroy them later
56 std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
57 EXPECT_NE(s1, nullptr);
59 std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
60 EXPECT_NE(s2, nullptr);
64 std::shared_ptr<ChildWatchdog> s3 =
65 SingletonBasicUsage<ChildWatchdog>::try_get();
66 EXPECT_NE(s3, nullptr);
69 EXPECT_EQ(vault.registeredSingletonCount(), 2);
70 EXPECT_EQ(vault.livingSingletonCount(), 2);
73 vault.destroyInstances();
74 EXPECT_EQ(vault.registeredSingletonCount(), 2);
75 EXPECT_EQ(vault.livingSingletonCount(), 0);
78 struct DirectUsageTag {};
79 template <typename T, typename Tag = detail::DefaultTag>
80 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
82 TEST(Singleton, DirectUsage) {
83 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
85 EXPECT_EQ(vault.registeredSingletonCount(), 0);
87 // Verify we can get to the underlying singletons via directly using
88 // the singleton definition.
89 SingletonDirectUsage<Watchdog> watchdog;
91 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
92 EXPECT_EQ(vault.registeredSingletonCount(), 2);
93 vault.registrationComplete();
95 EXPECT_NE(watchdog.try_get(), nullptr);
96 EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
97 EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
98 EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
100 vault.destroyInstances();
103 struct NamedUsageTag {};
104 template <typename T, typename Tag = detail::DefaultTag>
105 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
107 TEST(Singleton, NamedUsage) {
108 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
110 EXPECT_EQ(vault.registeredSingletonCount(), 0);
112 // Define two named Watchdog singletons and one unnamed singleton.
115 typedef detail::DefaultTag Watchdog3;
116 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
117 EXPECT_EQ(vault.registeredSingletonCount(), 1);
118 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
119 EXPECT_EQ(vault.registeredSingletonCount(), 2);
120 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
121 EXPECT_EQ(vault.registeredSingletonCount(), 3);
123 vault.registrationComplete();
125 // Verify our three singletons are distinct and non-nullptr.
126 auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
127 EXPECT_EQ(s1, watchdog1_singleton.try_get());
128 auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
129 EXPECT_EQ(s2, watchdog2_singleton.try_get());
131 auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
132 EXPECT_EQ(s3, watchdog3_singleton.try_get());
136 // Verify the "default" singleton is the same as the DefaultTag-tagged
138 auto s4 = SingletonNamedUsage<Watchdog>::try_get();
139 EXPECT_EQ(s4, watchdog3_singleton.try_get());
142 vault.destroyInstances();
145 struct NaughtyUsageTag {};
146 template <typename T, typename Tag = detail::DefaultTag>
147 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
148 struct NaughtyUsageTag2 {};
149 template <typename T, typename Tag = detail::DefaultTag>
150 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
152 // Some pathological cases such as getting unregistered singletons,
153 // double registration, etc.
154 TEST(Singleton, NaughtyUsage) {
155 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
157 vault.registrationComplete();
160 EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
161 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
163 vault.destroyInstances();
165 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
167 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
168 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
170 // double registration
171 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
173 vault2.destroyInstances();
175 // double registration after destroy
176 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
180 struct SharedPtrUsageTag {};
181 template <typename T, typename Tag = detail::DefaultTag>
182 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
184 // TODO (anob): revisit this test
185 TEST(Singleton, SharedPtrUsage) {
186 struct WatchdogHolder {
189 LOG(ERROR) << "The following log message with stack trace is expected";
193 std::shared_ptr<Watchdog> watchdog;
196 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
198 EXPECT_EQ(vault.registeredSingletonCount(), 0);
199 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
200 EXPECT_EQ(vault.registeredSingletonCount(), 1);
202 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
203 EXPECT_EQ(vault.registeredSingletonCount(), 2);
206 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
208 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
210 vault.registrationComplete();
212 // Initilize holder singleton first, so that it's the last one to be
214 watchdog_holder_singleton.try_get();
216 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
217 EXPECT_NE(s1, nullptr);
219 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
220 EXPECT_NE(s2, nullptr);
224 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
226 auto shared_s1 = weak_s1.lock();
227 EXPECT_EQ(shared_s1.get(), s1);
228 EXPECT_EQ(shared_s1.use_count(), 2);
230 auto old_serial = shared_s1->serial_number;
234 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
235 auto locked = named_weak_s1.lock();
236 EXPECT_NE(locked.get(), shared_s1.get());
239 // We should release externally locked shared_ptr, otherwise it will be
241 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
243 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
245 auto start_time = std::chrono::steady_clock::now();
246 vault.destroyInstances();
247 auto duration = std::chrono::steady_clock::now() - start_time;
248 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
249 duration < std::chrono::seconds{6});
251 EXPECT_EQ(vault.registeredSingletonCount(), 4);
252 EXPECT_EQ(vault.livingSingletonCount(), 0);
254 EXPECT_TRUE(weak_s1.expired());
256 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
257 EXPECT_FALSE(empty_s1.lock());
259 vault.reenableInstances();
262 // Singleton should be re-created only after reenableInstances() was called.
263 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
264 // Track serial number rather than pointer since the memory could be
265 // re-used when we create new_s1.
266 EXPECT_NE(new_s1->serial_number, old_serial);
269 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
270 auto new_s1_shared = new_s1_weak.lock();
271 std::thread t([new_s1_shared]() mutable {
272 std::this_thread::sleep_for(std::chrono::seconds{2});
273 new_s1_shared.reset();
275 new_s1_shared.reset();
277 auto start_time = std::chrono::steady_clock::now();
278 vault.destroyInstances();
279 auto duration = std::chrono::steady_clock::now() - start_time;
280 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
281 duration < std::chrono::seconds{3});
283 EXPECT_TRUE(new_s1_weak.expired());
287 // Some classes to test singleton dependencies. NeedySingleton has a
288 // dependency on NeededSingleton, which happens during its
291 template <typename T, typename Tag = detail::DefaultTag>
292 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
294 struct NeededSingleton {};
295 struct NeedySingleton {
297 auto unused = SingletonNeedy<NeededSingleton>::try_get();
298 EXPECT_NE(unused, nullptr);
302 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
303 struct SelfNeedyTag {};
304 template <typename T, typename Tag = detail::DefaultTag>
305 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
307 struct SelfNeedySingleton {
308 SelfNeedySingleton() {
309 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
310 EXPECT_NE(unused, nullptr);
314 TEST(Singleton, SingletonDependencies) {
315 SingletonNeedy<NeededSingleton> needed_singleton;
316 SingletonNeedy<NeedySingleton> needy_singleton;
317 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
319 needy_vault.registrationComplete();
321 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
322 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
324 auto needy = SingletonNeedy<NeedySingleton>::try_get();
325 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
327 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
328 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
330 self_needy_vault.registrationComplete();
331 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
335 // A test to ensure multiple threads contending on singleton creation
336 // properly wait for creation rather than thinking it is a circular
338 class Slowpoke : public Watchdog {
340 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
343 struct ConcurrencyTag {};
344 template <typename T, typename Tag = detail::DefaultTag>
345 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
347 TEST(Singleton, SingletonConcurrency) {
348 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
349 SingletonConcurrency<Slowpoke> slowpoke_singleton;
350 vault.registrationComplete();
352 std::mutex gatekeeper;
354 auto func = [&gatekeeper]() {
357 auto unused = SingletonConcurrency<Slowpoke>::try_get();
360 EXPECT_EQ(vault.livingSingletonCount(), 0);
361 std::vector<std::thread> threads;
362 for (int i = 0; i < 100; ++i) {
363 threads.emplace_back(func);
365 // If circular dependency checks fail, the unlock would trigger a
366 // crash. Instead, it succeeds, and we have exactly one living
369 for (auto& t : threads) {
372 EXPECT_EQ(vault.livingSingletonCount(), 1);
375 struct ErrorConstructor {
376 static size_t constructCount_;
378 if ((constructCount_++) == 0) {
379 throw std::runtime_error("first time fails");
383 size_t ErrorConstructor::constructCount_(0);
385 struct CreationErrorTag {};
386 template <typename T, typename Tag = detail::DefaultTag>
387 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
389 TEST(Singleton, SingletonCreationError) {
390 SingletonVault::singleton<CreationErrorTag>();
391 SingletonCreationError<ErrorConstructor> error_once_singleton;
393 // first time should error out
394 EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
396 // second time it'll work fine
397 error_once_singleton.get_weak().lock();
401 struct ConcurrencyStressTag {};
402 template <typename T, typename Tag = detail::DefaultTag>
403 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
405 TEST(Singleton, SingletonConcurrencyStress) {
406 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
407 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
409 std::vector<std::thread> ts;
410 for (size_t i = 0; i < 100; ++i) {
411 ts.emplace_back([&]() {
412 slowpoke_singleton.get_weak().lock();
416 for (size_t i = 0; i < 100; ++i) {
417 std::chrono::milliseconds d(20);
419 std::this_thread::sleep_for(d);
420 vault.destroyInstances();
421 std::this_thread::sleep_for(d);
422 vault.destroyInstances();
431 struct EagerInitSyncTag {};
433 template <typename T, typename Tag = detail::DefaultTag>
434 using SingletonEagerInitSync = Singleton<T, Tag, EagerInitSyncTag>;
435 TEST(Singleton, SingletonEagerInitSync) {
436 auto& vault = *SingletonVault::singleton<EagerInitSyncTag>();
437 bool didEagerInit = false;
438 auto sing = SingletonEagerInitSync<std::string>(
439 [&] {didEagerInit = true; return new std::string("foo"); })
441 vault.registrationComplete();
442 EXPECT_FALSE(didEagerInit);
444 EXPECT_TRUE(didEagerInit);
445 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
449 struct EagerInitAsyncTag {};
451 template <typename T, typename Tag = detail::DefaultTag>
452 using SingletonEagerInitAsync = Singleton<T, Tag, EagerInitAsyncTag>;
453 TEST(Singleton, SingletonEagerInitAsync) {
454 auto& vault = *SingletonVault::singleton<EagerInitAsyncTag>();
455 bool didEagerInit = false;
456 auto sing = SingletonEagerInitAsync<std::string>(
457 [&] {didEagerInit = true; return new std::string("foo"); })
461 vault.registrationComplete();
462 EXPECT_FALSE(didEagerInit);
463 vault.doEagerInitVia(eb, &done);
466 EXPECT_TRUE(didEagerInit);
467 sing.get_weak(); // (avoid compile error complaining about unused var 'sing')
471 class TestEagerInitParallelExecutor : public folly::Executor {
473 explicit TestEagerInitParallelExecutor(const size_t threadCount) {
474 eventBases_.reserve(threadCount);
475 threads_.reserve(threadCount);
476 for (size_t i = 0; i < threadCount; i++) {
477 eventBases_.push_back(std::make_shared<folly::EventBase>());
478 auto eb = eventBases_.back();
479 threads_.emplace_back(std::make_shared<std::thread>(
480 [eb] { eb->loopForever(); }));
484 virtual ~TestEagerInitParallelExecutor() override {
485 for (auto eb : eventBases_) {
486 eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
488 for (auto thread : threads_) {
493 virtual void add(folly::Func func) override {
494 const auto index = (counter_ ++) % eventBases_.size();
495 eventBases_[index]->add(func);
499 std::vector<std::shared_ptr<folly::EventBase>> eventBases_;
500 std::vector<std::shared_ptr<std::thread>> threads_;
501 std::atomic<size_t> counter_ {0};
506 struct EagerInitParallelTag {};
508 template <typename T, typename Tag = detail::DefaultTag>
509 using SingletonEagerInitParallel = Singleton<T, Tag, EagerInitParallelTag>;
510 TEST(Singleton, SingletonEagerInitParallel) {
511 const static size_t kIters = 1000;
512 const static size_t kThreads = 20;
514 std::atomic<size_t> initCounter;
516 auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
518 auto sing = SingletonEagerInitParallel<std::string>(
519 [&] {++initCounter; return new std::string(""); })
522 for (size_t i = 0; i < kIters; i++) {
524 // clean up each time
525 vault.destroyInstances();
526 vault.reenableInstances();
529 initCounter.store(0);
532 std::vector<std::shared_ptr<std::thread>> threads;
533 boost::barrier barrier(kThreads);
534 TestEagerInitParallelExecutor exe(kThreads);
535 vault.registrationComplete();
537 EXPECT_EQ(0, initCounter.load());
539 for (size_t j = 0; j < kThreads; j++) {
540 threads.push_back(std::make_shared<std::thread>([&] {
542 vault.doEagerInitVia(exe);
546 for (auto thread : threads) {
551 EXPECT_EQ(1, initCounter.load());
553 sing.get_weak(); // (avoid compile error complaining about unused var)
557 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
558 // singleton. Meyers are insanely fast, but (hopefully) Folly
559 // singletons are fast "enough."
560 int* getMeyersSingleton() {
561 static auto ret = new int(0);
565 int normal_singleton_value = 0;
566 int* getNormalSingleton() {
567 doNotOptimizeAway(&normal_singleton_value);
568 return &normal_singleton_value;
572 template <typename T, typename Tag = detail::DefaultTag>
573 using SingletonMock = Singleton <T, Tag, MockTag>;
575 // Verify that existing Singleton's can be overridden
576 // using the make_mock functionality.
577 TEST(Singleton, MockTest) {
578 auto& vault = *SingletonVault::singleton<MockTag>();
580 SingletonMock<Watchdog> watchdog_singleton;
581 vault.registrationComplete();
583 // Registring singletons after registrationComplete called works
584 // with make_mock (but not with Singleton ctor).
585 EXPECT_EQ(vault.registeredSingletonCount(), 1);
586 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
588 // Override existing mock using make_mock.
589 SingletonMock<Watchdog>::make_mock();
591 EXPECT_EQ(vault.registeredSingletonCount(), 1);
592 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
594 // If serial_count value is the same, then singleton was not replaced.
595 EXPECT_NE(serial_count_first, serial_count_mock);
598 struct BenchmarkSingleton {
602 BENCHMARK(NormalSingleton, n) {
603 for (size_t i = 0; i < n; ++i) {
604 doNotOptimizeAway(getNormalSingleton());
608 BENCHMARK_RELATIVE(MeyersSingleton, n) {
609 for (size_t i = 0; i < n; ++i) {
610 doNotOptimizeAway(getMeyersSingleton());
614 struct BenchmarkTag {};
615 template <typename T, typename Tag = detail::DefaultTag>
616 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
621 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
622 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
624 BENCHMARK_RELATIVE(FollySingleton, n) {
625 for (size_t i = 0; i < n; ++i) {
626 SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
630 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
631 for (size_t i = 0; i < n; ++i) {
632 SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
636 int main(int argc, char* argv[]) {
637 testing::InitGoogleTest(&argc, argv);
638 google::InitGoogleLogging(argv[0]);
639 gflags::ParseCommandLineFlags(&argc, &argv, true);
641 SingletonVault::singleton()->registrationComplete();
643 auto ret = RUN_ALL_TESTS();
645 folly::runBenchmarksOnFlag();