2 * Copyright 2014 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/experimental/Singleton.h>
21 #include <folly/Benchmark.h>
23 #include <glog/logging.h>
24 #include <gtest/gtest.h>
26 using namespace folly;
28 // A simple class that tracks how often instances of the class and
29 // subclasses are created, and the ordering. Also tracks a global
30 // unique counter for each object.
31 std::atomic<size_t> global_counter(19770326);
33 static std::vector<Watchdog*> creation_order;
34 Watchdog() : serial_number(++global_counter) {
35 creation_order.push_back(this);
39 if (creation_order.back() != this) {
40 throw std::out_of_range("Watchdog destruction order mismatch");
42 creation_order.pop_back();
45 const size_t serial_number;
46 size_t livingWatchdogCount() const { return creation_order.size(); }
48 Watchdog(const Watchdog&) = delete;
49 Watchdog& operator=(const Watchdog&) = delete;
50 Watchdog(Watchdog&&) noexcept = default;
53 std::vector<Watchdog*> Watchdog::creation_order;
55 // Some basic types we use for tracking.
56 struct ChildWatchdog : public Watchdog {};
57 struct GlobalWatchdog : public Watchdog {};
58 struct UnregisteredWatchdog : public Watchdog {};
61 Singleton<GlobalWatchdog> global_watchdog;
64 // Test basic global usage (the default way singletons will generally
66 TEST(Singleton, BasicGlobalUsage) {
67 EXPECT_EQ(Watchdog::creation_order.size(), 0);
68 EXPECT_EQ(SingletonVault::singleton()->registeredSingletonCount(), 1);
69 EXPECT_EQ(SingletonVault::singleton()->livingSingletonCount(), 0);
70 auto wd1 = Singleton<GlobalWatchdog>::get();
71 EXPECT_NE(wd1, nullptr);
72 EXPECT_EQ(Watchdog::creation_order.size(), 1);
73 auto wd2 = Singleton<GlobalWatchdog>::get();
74 EXPECT_NE(wd2, nullptr);
76 EXPECT_EQ(Watchdog::creation_order.size(), 1);
77 SingletonVault::singleton()->destroyInstances();
78 EXPECT_EQ(Watchdog::creation_order.size(), 0);
81 TEST(Singleton, MissingSingleton) {
82 EXPECT_THROW([]() { auto u = Singleton<UnregisteredWatchdog>::get(); }(),
86 struct BasicUsageTag {};
87 template <typename T, typename Tag = detail::DefaultTag>
88 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
90 // Exercise some basic codepaths ensuring registration order and
91 // destruction order happen as expected, that instances are created
92 // when expected, etc etc.
93 TEST(Singleton, BasicUsage) {
94 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
96 EXPECT_EQ(vault.registeredSingletonCount(), 0);
97 SingletonBasicUsage<Watchdog> watchdog_singleton;
98 EXPECT_EQ(vault.registeredSingletonCount(), 1);
100 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
101 EXPECT_EQ(vault.registeredSingletonCount(), 2);
103 vault.registrationComplete();
105 Watchdog* s1 = SingletonBasicUsage<Watchdog>::get();
106 EXPECT_NE(s1, nullptr);
108 Watchdog* s2 = SingletonBasicUsage<Watchdog>::get();
109 EXPECT_NE(s2, nullptr);
113 auto s3 = SingletonBasicUsage<ChildWatchdog>::get();
114 EXPECT_NE(s3, nullptr);
117 EXPECT_EQ(vault.registeredSingletonCount(), 2);
118 EXPECT_EQ(vault.livingSingletonCount(), 2);
120 vault.destroyInstances();
121 EXPECT_EQ(vault.registeredSingletonCount(), 2);
122 EXPECT_EQ(vault.livingSingletonCount(), 0);
125 struct DirectUsageTag {};
126 template <typename T, typename Tag = detail::DefaultTag>
127 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
129 TEST(Singleton, DirectUsage) {
130 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
132 EXPECT_EQ(vault.registeredSingletonCount(), 0);
134 // Verify we can get to the underlying singletons via directly using
135 // the singleton definition.
136 SingletonDirectUsage<Watchdog> watchdog;
138 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
139 EXPECT_EQ(vault.registeredSingletonCount(), 2);
140 vault.registrationComplete();
142 EXPECT_NE(watchdog.ptr(), nullptr);
143 EXPECT_EQ(watchdog.ptr(), SingletonDirectUsage<Watchdog>::get());
144 EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
145 EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
146 EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
148 vault.destroyInstances();
151 struct NamedUsageTag {};
152 template <typename T, typename Tag = detail::DefaultTag>
153 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
155 TEST(Singleton, NamedUsage) {
156 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
158 EXPECT_EQ(vault.registeredSingletonCount(), 0);
160 // Define two named Watchdog singletons and one unnamed singleton.
163 typedef detail::DefaultTag Watchdog3;
164 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
165 EXPECT_EQ(vault.registeredSingletonCount(), 1);
166 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
167 EXPECT_EQ(vault.registeredSingletonCount(), 2);
168 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
169 EXPECT_EQ(vault.registeredSingletonCount(), 3);
171 vault.registrationComplete();
173 // Verify our three singletons are distinct and non-nullptr.
174 Watchdog* s1 = SingletonNamedUsage<Watchdog, Watchdog1>::get();
175 EXPECT_EQ(s1, watchdog1_singleton.ptr());
176 Watchdog* s2 = SingletonNamedUsage<Watchdog, Watchdog2>::get();
177 EXPECT_EQ(s2, watchdog2_singleton.ptr());
179 Watchdog* s3 = SingletonNamedUsage<Watchdog, Watchdog3>::get();
180 EXPECT_EQ(s3, watchdog3_singleton.ptr());
184 // Verify the "default" singleton is the same as the DefaultTag-tagged
186 Watchdog* s4 = SingletonNamedUsage<Watchdog>::get();
187 EXPECT_EQ(s4, watchdog3_singleton.ptr());
189 vault.destroyInstances();
192 struct NaughtyUsageTag {};
193 template <typename T, typename Tag = detail::DefaultTag>
194 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
195 struct NaughtyUsageTag2 {};
196 template <typename T, typename Tag = detail::DefaultTag>
197 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
199 // Some pathological cases such as getting unregistered singletons,
200 // double registration, etc.
201 TEST(Singleton, NaughtyUsage) {
202 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
204 vault.registrationComplete();
207 EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
208 EXPECT_THROW(SingletonNaughtyUsage<Watchdog>::get(), std::out_of_range);
210 vault.destroyInstances();
212 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
214 EXPECT_THROW(SingletonNaughtyUsage2<Watchdog>::get(), std::logic_error);
215 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
216 // double registration
218 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
221 vault2.destroyInstances();
222 // double registration after destroy
224 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
229 struct SharedPtrUsageTag {};
230 template <typename T, typename Tag = detail::DefaultTag>
231 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
233 TEST(Singleton, SharedPtrUsage) {
234 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
236 EXPECT_EQ(vault.registeredSingletonCount(), 0);
237 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
238 EXPECT_EQ(vault.registeredSingletonCount(), 1);
240 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
241 EXPECT_EQ(vault.registeredSingletonCount(), 2);
244 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
245 vault.registrationComplete();
247 Watchdog* s1 = SingletonSharedPtrUsage<Watchdog>::get();
248 EXPECT_NE(s1, nullptr);
250 Watchdog* s2 = SingletonSharedPtrUsage<Watchdog>::get();
251 EXPECT_NE(s2, nullptr);
255 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
256 auto shared_s1 = weak_s1.lock();
257 EXPECT_EQ(shared_s1.get(), s1);
258 EXPECT_EQ(shared_s1.use_count(), 2);
262 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
263 auto locked = named_weak_s1.lock();
264 EXPECT_NE(locked.get(), shared_s1.get());
267 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
269 auto start_time = std::chrono::steady_clock::now();
270 vault.destroyInstances();
271 auto duration = std::chrono::steady_clock::now() - start_time;
272 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
273 duration < std::chrono::seconds{6});
275 EXPECT_EQ(vault.registeredSingletonCount(), 3);
276 EXPECT_EQ(vault.livingSingletonCount(), 0);
278 EXPECT_EQ(shared_s1.use_count(), 1);
279 EXPECT_EQ(shared_s1.get(), s1);
281 auto locked_s1 = weak_s1.lock();
282 EXPECT_EQ(locked_s1.get(), s1);
283 EXPECT_EQ(shared_s1.use_count(), 2);
285 EXPECT_EQ(shared_s1.use_count(), 1);
287 // Track serial number rather than pointer since the memory could be
288 // re-used when we create new_s1.
289 auto old_serial = shared_s1->serial_number;
291 locked_s1 = weak_s1.lock();
292 EXPECT_TRUE(weak_s1.expired());
294 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
295 EXPECT_FALSE(empty_s1.lock());
297 vault.reenableInstances();
299 // Singleton should be re-created only after reenableInstances() was called.
300 Watchdog* new_s1 = SingletonSharedPtrUsage<Watchdog>::get();
301 EXPECT_NE(new_s1->serial_number, old_serial);
303 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
304 auto new_s1_shared = new_s1_weak.lock();
305 std::thread t([new_s1_shared]() mutable {
306 std::this_thread::sleep_for(std::chrono::seconds{2});
307 new_s1_shared.reset();
309 new_s1_shared.reset();
311 auto start_time = std::chrono::steady_clock::now();
312 vault.destroyInstances();
313 auto duration = std::chrono::steady_clock::now() - start_time;
314 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
315 duration < std::chrono::seconds{3});
317 EXPECT_TRUE(new_s1_weak.expired());
321 // Some classes to test singleton dependencies. NeedySingleton has a
322 // dependency on NeededSingleton, which happens during its
325 template <typename T, typename Tag = detail::DefaultTag>
326 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
328 struct NeededSingleton {};
329 struct NeedySingleton {
331 auto unused = SingletonNeedy<NeededSingleton>::get();
332 EXPECT_NE(unused, nullptr);
336 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
337 struct SelfNeedyTag {};
338 template <typename T, typename Tag = detail::DefaultTag>
339 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
341 struct SelfNeedySingleton {
342 SelfNeedySingleton() {
343 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::get();
344 EXPECT_NE(unused, nullptr);
348 TEST(Singleton, SingletonDependencies) {
349 SingletonNeedy<NeededSingleton> needed_singleton;
350 SingletonNeedy<NeedySingleton> needy_singleton;
351 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
353 needy_vault.registrationComplete();
355 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
356 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
358 auto needy = SingletonNeedy<NeedySingleton>::get();
359 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
361 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
362 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
364 self_needy_vault.registrationComplete();
366 SingletonSelfNeedy<SelfNeedySingleton>::get();
371 // A test to ensure multiple threads contending on singleton creation
372 // properly wait for creation rather than thinking it is a circular
374 class Slowpoke : public Watchdog {
376 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
379 struct ConcurrencyTag {};
380 template <typename T, typename Tag = detail::DefaultTag>
381 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
383 TEST(Singleton, SingletonConcurrency) {
384 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
385 SingletonConcurrency<Slowpoke> slowpoke_singleton;
386 vault.registrationComplete();
388 std::mutex gatekeeper;
390 auto func = [&gatekeeper]() {
393 auto unused = SingletonConcurrency<Slowpoke>::get();
396 EXPECT_EQ(vault.livingSingletonCount(), 0);
397 std::vector<std::thread> threads;
398 for (int i = 0; i < 100; ++i) {
399 threads.emplace_back(func);
401 // If circular dependency checks fail, the unlock would trigger a
402 // crash. Instead, it succeeds, and we have exactly one living
405 for (auto& t : threads) {
408 EXPECT_EQ(vault.livingSingletonCount(), 1);
411 struct ConcurrencyStressTag {};
412 template <typename T, typename Tag = detail::DefaultTag>
413 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
415 TEST(Singleton, SingletonConcurrencyStress) {
416 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
417 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
419 std::vector<std::thread> ts;
420 for (size_t i = 0; i < 100; ++i) {
421 ts.emplace_back([&]() {
422 slowpoke_singleton.get_weak().lock();
426 for (size_t i = 0; i < 100; ++i) {
427 std::chrono::milliseconds d(20);
429 std::this_thread::sleep_for(d);
430 vault.destroyInstances();
431 std::this_thread::sleep_for(d);
432 vault.destroyInstances();
440 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
441 // singleton. Meyers are insanely fast, but (hopefully) Folly
442 // singletons are fast "enough."
443 int* getMeyersSingleton() {
444 static auto ret = new int(0);
448 int normal_singleton_value = 0;
449 int* getNormalSingleton() {
450 doNotOptimizeAway(&normal_singleton_value);
451 return &normal_singleton_value;
455 template <typename T, typename Tag = detail::DefaultTag>
456 using SingletonMock = Singleton <T, Tag, MockTag>;
458 // Verify that existing Singleton's can be overridden
459 // using the make_mock functionality.
460 TEST(Singleton, MockTest) {
461 auto& vault = *SingletonVault::singleton<MockTag>();
463 SingletonMock<Watchdog> watchdog_singleton;
464 vault.registrationComplete();
466 // Registring singletons after registrationComplete called works
467 // with make_mock (but not with Singleton ctor).
468 EXPECT_EQ(vault.registeredSingletonCount(), 1);
469 int serial_count_first = SingletonMock<Watchdog>::get()->serial_number;
471 // Override existing mock using make_mock.
472 SingletonMock<Watchdog>::make_mock();
474 EXPECT_EQ(vault.registeredSingletonCount(), 1);
475 int serial_count_mock = SingletonMock<Watchdog>::get()->serial_number;
477 // If serial_count value is the same, then singleton was not replaced.
478 EXPECT_NE(serial_count_first, serial_count_mock);
481 struct BenchmarkSingleton {
485 BENCHMARK(NormalSingleton, n) {
486 for (size_t i = 0; i < n; ++i) {
487 doNotOptimizeAway(getNormalSingleton());
491 BENCHMARK_RELATIVE(MeyersSingleton, n) {
492 for (size_t i = 0; i < n; ++i) {
493 doNotOptimizeAway(getMeyersSingleton());
497 struct BenchmarkTag {};
498 template <typename T, typename Tag = detail::DefaultTag>
499 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
501 SingletonBenchmark<BenchmarkSingleton> benchmark_singleton;
503 BENCHMARK_RELATIVE(FollySingletonSlow, n) {
504 for (size_t i = 0; i < n; ++i) {
505 doNotOptimizeAway(SingletonBenchmark<BenchmarkSingleton>::get());
509 BENCHMARK_RELATIVE(FollySingletonFast, n) {
510 for (size_t i = 0; i < n; ++i) {
511 doNotOptimizeAway(benchmark_singleton.get_fast());
515 BENCHMARK_RELATIVE(FollySingletonFastWeak, n) {
516 for (size_t i = 0; i < n; ++i) {
517 benchmark_singleton.get_weak_fast();
521 int main(int argc, char* argv[]) {
522 testing::InitGoogleTest(&argc, argv);
523 google::InitGoogleLogging(argv[0]);
524 google::ParseCommandLineFlags(&argc, &argv, true);
526 SingletonVault::singleton()->registrationComplete();
528 auto ret = RUN_ALL_TESTS();
530 folly::runBenchmarksOnFlag();