folly Singleton: "eager" option to initialize upfront
[folly.git] / folly / test / SingletonTest.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <thread>
18
19 #include <folly/Singleton.h>
20 #include <folly/io/async/EventBase.h>
21
22 #include <folly/Benchmark.h>
23
24 #include <glog/logging.h>
25 #include <gtest/gtest.h>
26 #include <boost/thread/barrier.hpp>
27
28 using namespace folly;
29
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);
34 struct Watchdog {
35   static std::vector<Watchdog*> creation_order;
36   Watchdog() : serial_number(++global_counter) {
37     creation_order.push_back(this);
38   }
39
40   ~Watchdog() {
41     if (creation_order.back() != this) {
42       throw std::out_of_range("Watchdog destruction order mismatch");
43     }
44     creation_order.pop_back();
45   }
46
47   const size_t serial_number;
48   size_t livingWatchdogCount() const { return creation_order.size(); }
49
50   Watchdog(const Watchdog&) = delete;
51   Watchdog& operator=(const Watchdog&) = delete;
52   Watchdog(Watchdog&&) noexcept = default;
53 };
54
55 std::vector<Watchdog*> Watchdog::creation_order;
56
57 // Some basic types we use for tracking.
58 struct ChildWatchdog : public Watchdog {};
59 struct GlobalWatchdog : public Watchdog {};
60 struct UnregisteredWatchdog : public Watchdog {};
61
62 namespace {
63 Singleton<GlobalWatchdog> global_watchdog;
64 }
65
66 // Test basic global usage (the default way singletons will generally
67 // be used).
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);
72
73   {
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);
81   }
82
83   SingletonVault::singleton()->destroyInstances();
84   EXPECT_EQ(Watchdog::creation_order.size(), 0);
85 }
86
87 TEST(Singleton, MissingSingleton) {
88   EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
89       "");
90 }
91
92 struct BasicUsageTag {};
93 template <typename T, typename Tag = detail::DefaultTag>
94 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
95
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>();
101
102   EXPECT_EQ(vault.registeredSingletonCount(), 0);
103   SingletonBasicUsage<Watchdog> watchdog_singleton;
104   EXPECT_EQ(vault.registeredSingletonCount(), 1);
105
106   SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
107   EXPECT_EQ(vault.registeredSingletonCount(), 2);
108
109   vault.registrationComplete();
110
111   // limit a scope to release references so we can destroy them later
112   {
113     std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
114     EXPECT_NE(s1, nullptr);
115
116     std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
117     EXPECT_NE(s2, nullptr);
118
119     EXPECT_EQ(s1, s2);
120
121     std::shared_ptr<ChildWatchdog> s3 =
122       SingletonBasicUsage<ChildWatchdog>::try_get();
123     EXPECT_NE(s3, nullptr);
124     EXPECT_NE(s2, s3);
125
126     EXPECT_EQ(vault.registeredSingletonCount(), 2);
127     EXPECT_EQ(vault.livingSingletonCount(), 2);
128   }
129
130   vault.destroyInstances();
131   EXPECT_EQ(vault.registeredSingletonCount(), 2);
132   EXPECT_EQ(vault.livingSingletonCount(), 0);
133 }
134
135 struct DirectUsageTag {};
136 template <typename T, typename Tag = detail::DefaultTag>
137 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
138
139 TEST(Singleton, DirectUsage) {
140   auto& vault = *SingletonVault::singleton<DirectUsageTag>();
141
142   EXPECT_EQ(vault.registeredSingletonCount(), 0);
143
144   // Verify we can get to the underlying singletons via directly using
145   // the singleton definition.
146   SingletonDirectUsage<Watchdog> watchdog;
147   struct TestTag {};
148   SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
149   EXPECT_EQ(vault.registeredSingletonCount(), 2);
150   vault.registrationComplete();
151
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);
156
157   vault.destroyInstances();
158 }
159
160 struct NamedUsageTag {};
161 template <typename T, typename Tag = detail::DefaultTag>
162 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
163
164 TEST(Singleton, NamedUsage) {
165   auto& vault = *SingletonVault::singleton<NamedUsageTag>();
166
167   EXPECT_EQ(vault.registeredSingletonCount(), 0);
168
169   // Define two named Watchdog singletons and one unnamed singleton.
170   struct Watchdog1 {};
171   struct Watchdog2 {};
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);
179
180   vault.registrationComplete();
181   {
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());
187     EXPECT_NE(s1, s2);
188     auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
189     EXPECT_EQ(s3, watchdog3_singleton.try_get());
190     EXPECT_NE(s3, s1);
191     EXPECT_NE(s3, s2);
192
193     // Verify the "default" singleton is the same as the DefaultTag-tagged
194     // singleton.
195     auto s4 = SingletonNamedUsage<Watchdog>::try_get();
196     EXPECT_EQ(s4, watchdog3_singleton.try_get());
197   }
198
199   vault.destroyInstances();
200 }
201
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>;
208
209 // Some pathological cases such as getting unregistered singletons,
210 // double registration, etc.
211 TEST(Singleton, NaughtyUsage) {
212   auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
213
214   vault.registrationComplete();
215
216   // Unregistered.
217   EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
218   EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
219
220   vault.destroyInstances();
221
222   auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
223
224    EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
225   SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
226
227   // double registration
228   EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
229                "");
230   vault2.destroyInstances();
231
232   // double registration after destroy
233   EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
234                "");
235 }
236
237 struct SharedPtrUsageTag {};
238 template <typename T, typename Tag = detail::DefaultTag>
239 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
240
241 // TODO (anob): revisit this test
242 TEST(Singleton, SharedPtrUsage) {
243   struct WatchdogHolder {
244     ~WatchdogHolder() {
245       if (watchdog) {
246         LOG(ERROR) << "The following log message with stack trace is expected";
247       }
248     }
249
250     std::shared_ptr<Watchdog> watchdog;
251   };
252
253   auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
254
255   EXPECT_EQ(vault.registeredSingletonCount(), 0);
256   SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
257   EXPECT_EQ(vault.registeredSingletonCount(), 1);
258
259   SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
260   EXPECT_EQ(vault.registeredSingletonCount(), 2);
261
262   struct ATag {};
263   SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
264
265   SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
266
267   vault.registrationComplete();
268
269   // Initilize holder singleton first, so that it's the last one to be
270   // destroyed.
271   watchdog_holder_singleton.try_get();
272
273   auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
274   EXPECT_NE(s1, nullptr);
275
276   auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
277   EXPECT_NE(s2, nullptr);
278
279   EXPECT_EQ(s1, s2);
280
281   auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
282
283   auto shared_s1 = weak_s1.lock();
284   EXPECT_EQ(shared_s1.get(), s1);
285   EXPECT_EQ(shared_s1.use_count(), 2);
286
287   auto old_serial = shared_s1->serial_number;
288
289   {
290     auto named_weak_s1 =
291       SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
292     auto locked = named_weak_s1.lock();
293     EXPECT_NE(locked.get(), shared_s1.get());
294   }
295
296   // We should release externally locked shared_ptr, otherwise it will be
297   // considered a leak
298   watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
299
300   LOG(ERROR) << "The following log message regarding shared_ptr is expected";
301   {
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});
307   }
308   EXPECT_EQ(vault.registeredSingletonCount(), 4);
309   EXPECT_EQ(vault.livingSingletonCount(), 0);
310
311   EXPECT_TRUE(weak_s1.expired());
312
313   auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
314   EXPECT_FALSE(empty_s1.lock());
315
316   vault.reenableInstances();
317
318   {
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);
324   }
325
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();
331     });
332   new_s1_shared.reset();
333   {
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});
339   }
340   EXPECT_TRUE(new_s1_weak.expired());
341   t.join();
342 }
343
344 // Some classes to test singleton dependencies.  NeedySingleton has a
345 // dependency on NeededSingleton, which happens during its
346 // construction.
347 struct NeedyTag {};
348 template <typename T, typename Tag = detail::DefaultTag>
349 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
350
351 struct NeededSingleton {};
352 struct NeedySingleton {
353   NeedySingleton() {
354     auto unused = SingletonNeedy<NeededSingleton>::try_get();
355     EXPECT_NE(unused, nullptr);
356   }
357 };
358
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>;
363
364 struct SelfNeedySingleton {
365   SelfNeedySingleton() {
366     auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
367     EXPECT_NE(unused, nullptr);
368   }
369 };
370
371 TEST(Singleton, SingletonDependencies) {
372   SingletonNeedy<NeededSingleton> needed_singleton;
373   SingletonNeedy<NeedySingleton> needy_singleton;
374   auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
375
376   needy_vault.registrationComplete();
377
378   EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
379   EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
380
381   auto needy = SingletonNeedy<NeedySingleton>::try_get();
382   EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
383
384   SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
385   auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
386
387   self_needy_vault.registrationComplete();
388   EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
389       "");
390 }
391
392 // A test to ensure multiple threads contending on singleton creation
393 // properly wait for creation rather than thinking it is a circular
394 // dependency.
395 class Slowpoke : public Watchdog {
396  public:
397   Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
398 };
399
400 struct ConcurrencyTag {};
401 template <typename T, typename Tag = detail::DefaultTag>
402 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
403
404 TEST(Singleton, SingletonConcurrency) {
405   auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
406   SingletonConcurrency<Slowpoke> slowpoke_singleton;
407   vault.registrationComplete();
408
409   std::mutex gatekeeper;
410   gatekeeper.lock();
411   auto func = [&gatekeeper]() {
412     gatekeeper.lock();
413     gatekeeper.unlock();
414     auto unused = SingletonConcurrency<Slowpoke>::try_get();
415   };
416
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);
421   }
422   // If circular dependency checks fail, the unlock would trigger a
423   // crash.  Instead, it succeeds, and we have exactly one living
424   // singleton.
425   gatekeeper.unlock();
426   for (auto& t : threads) {
427     t.join();
428   }
429   EXPECT_EQ(vault.livingSingletonCount(), 1);
430 }
431
432 struct ErrorConstructor {
433   static size_t constructCount_;
434   ErrorConstructor() {
435     if ((constructCount_++) == 0) {
436       throw std::runtime_error("first time fails");
437     }
438   }
439 };
440 size_t ErrorConstructor::constructCount_(0);
441
442 struct CreationErrorTag {};
443 template <typename T, typename Tag = detail::DefaultTag>
444 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
445
446 TEST(Singleton, SingletonCreationError) {
447   auto& vault = *SingletonVault::singleton<CreationErrorTag>();
448   SingletonCreationError<ErrorConstructor> error_once_singleton;
449
450   // first time should error out
451   EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
452
453   // second time it'll work fine
454   error_once_singleton.get_weak().lock();
455   SUCCEED();
456 }
457
458 struct ConcurrencyStressTag {};
459 template <typename T, typename Tag = detail::DefaultTag>
460 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
461
462 TEST(Singleton, SingletonConcurrencyStress) {
463   auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
464   SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
465
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();
470       });
471   }
472
473   for (size_t i = 0; i < 100; ++i) {
474     std::chrono::milliseconds d(20);
475
476     std::this_thread::sleep_for(d);
477     vault.destroyInstances();
478     std::this_thread::sleep_for(d);
479     vault.destroyInstances();
480   }
481
482   for (auto& t : ts) {
483     t.join();
484   }
485 }
486
487 namespace {
488 struct EagerInitSyncTag {};
489 }
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"); })
497               .shouldEagerInit();
498   vault.registrationComplete();
499   EXPECT_TRUE(didEagerInit);
500   sing.get_weak();  // (avoid compile error complaining about unused var 'sing')
501 }
502
503 namespace {
504 struct EagerInitAsyncTag {};
505 }
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"); })
513               .shouldEagerInit();
514   folly::EventBase eb;
515   vault.setEagerInitExecutor(&eb);
516   vault.registrationComplete();
517   EXPECT_FALSE(didEagerInit);
518   eb.loop();
519   EXPECT_TRUE(didEagerInit);
520   sing.get_weak();  // (avoid compile error complaining about unused var 'sing')
521 }
522
523 namespace {
524 class TestEagerInitParallelExecutor : public folly::Executor {
525  public:
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(); }));
534     }
535   }
536
537   virtual ~TestEagerInitParallelExecutor() override {
538     for (auto eb : eventBases_) {
539       eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); });
540     }
541     for (auto thread : threads_) {
542       thread->join();
543     }
544   }
545
546   virtual void add(folly::Func func) override {
547     const auto index = (counter_ ++) % eventBases_.size();
548     eventBases_[index]->add(func);
549   }
550
551  private:
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};
555 };
556 }  // namespace
557
558 namespace {
559 struct EagerInitParallelTag {};
560 }
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;
566
567   std::atomic<size_t> initCounter;
568
569   auto& vault = *SingletonVault::singleton<EagerInitParallelTag>();
570
571   auto sing = SingletonEagerInitParallel<std::string>(
572                   [&] {++initCounter; return new std::string(""); })
573               .shouldEagerInit();
574
575   for (size_t i = 0; i < kIters; i++) {
576     SCOPE_EXIT {
577       // clean up each time
578       vault.destroyInstances();
579       vault.reenableInstances();
580     };
581
582     initCounter.store(0);
583
584     {
585       boost::barrier barrier(kThreads + 1);
586       TestEagerInitParallelExecutor exe(kThreads);
587       vault.setEagerInitExecutor(&exe);
588       vault.registrationComplete(false);
589
590       EXPECT_EQ(0, initCounter.load());
591
592       for (size_t j = 0; j < kThreads; j++) {
593         exe.add([&] {
594           barrier.wait();
595           vault.startEagerInit();
596           barrier.wait();
597         });
598       }
599
600       barrier.wait();  // to await all threads' readiness
601       barrier.wait();  // to await all threads' completion
602     }
603
604     EXPECT_EQ(1, initCounter.load());
605
606     sing.get_weak();  // (avoid compile error complaining about unused var)
607   }
608 }
609
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);
615   return ret;
616 }
617
618 int normal_singleton_value = 0;
619 int* getNormalSingleton() {
620   doNotOptimizeAway(&normal_singleton_value);
621   return &normal_singleton_value;
622 }
623
624 struct MockTag {};
625 template <typename T, typename Tag = detail::DefaultTag>
626 using SingletonMock = Singleton <T, Tag, MockTag>;
627
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>();
632
633   SingletonMock<Watchdog> watchdog_singleton;
634   vault.registrationComplete();
635
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;
640
641   // Override existing mock using make_mock.
642   SingletonMock<Watchdog>::make_mock();
643
644   EXPECT_EQ(vault.registeredSingletonCount(), 1);
645   int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
646
647   // If serial_count value is the same, then singleton was not replaced.
648   EXPECT_NE(serial_count_first, serial_count_mock);
649 }
650
651 struct BenchmarkSingleton {
652   int val = 0;
653 };
654
655 BENCHMARK(NormalSingleton, n) {
656   for (size_t i = 0; i < n; ++i) {
657     doNotOptimizeAway(getNormalSingleton());
658   }
659 }
660
661 BENCHMARK_RELATIVE(MeyersSingleton, n) {
662   for (size_t i = 0; i < n; ++i) {
663     doNotOptimizeAway(getMeyersSingleton());
664   }
665 }
666
667 struct BenchmarkTag {};
668 template <typename T, typename Tag = detail::DefaultTag>
669 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
670
671 struct GetTag{};
672 struct GetWeakTag{};
673
674 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
675 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
676
677 BENCHMARK_RELATIVE(FollySingleton, n) {
678   for (size_t i = 0; i < n; ++i) {
679     SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
680   }
681 }
682
683 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
684   for (size_t i = 0; i < n; ++i) {
685     SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
686   }
687 }
688
689 int main(int argc, char* argv[]) {
690   testing::InitGoogleTest(&argc, argv);
691   google::InitGoogleLogging(argv[0]);
692   gflags::ParseCommandLineFlags(&argc, &argv, true);
693
694   SingletonVault::singleton()->registrationComplete();
695
696   auto ret = RUN_ALL_TESTS();
697   if (!ret) {
698     folly::runBenchmarksOnFlag();
699   }
700   return ret;
701 }