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>
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_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::get(); }(), "");
85 struct BasicUsageTag {};
86 template <typename T, typename Tag = detail::DefaultTag>
87 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
89 // Exercise some basic codepaths ensuring registration order and
90 // destruction order happen as expected, that instances are created
91 // when expected, etc etc.
92 TEST(Singleton, BasicUsage) {
93 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
95 EXPECT_EQ(vault.registeredSingletonCount(), 0);
96 SingletonBasicUsage<Watchdog> watchdog_singleton;
97 EXPECT_EQ(vault.registeredSingletonCount(), 1);
99 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
100 EXPECT_EQ(vault.registeredSingletonCount(), 2);
102 vault.registrationComplete();
104 Watchdog* s1 = SingletonBasicUsage<Watchdog>::get();
105 EXPECT_NE(s1, nullptr);
107 Watchdog* s2 = SingletonBasicUsage<Watchdog>::get();
108 EXPECT_NE(s2, nullptr);
112 auto s3 = SingletonBasicUsage<ChildWatchdog>::get();
113 EXPECT_NE(s3, nullptr);
116 EXPECT_EQ(vault.registeredSingletonCount(), 2);
117 EXPECT_EQ(vault.livingSingletonCount(), 2);
119 vault.destroyInstances();
120 EXPECT_EQ(vault.registeredSingletonCount(), 2);
121 EXPECT_EQ(vault.livingSingletonCount(), 0);
124 struct DirectUsageTag {};
125 template <typename T, typename Tag = detail::DefaultTag>
126 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
128 TEST(Singleton, DirectUsage) {
129 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
131 EXPECT_EQ(vault.registeredSingletonCount(), 0);
133 // Verify we can get to the underlying singletons via directly using
134 // the singleton definition.
135 SingletonDirectUsage<Watchdog> watchdog;
137 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
138 EXPECT_EQ(vault.registeredSingletonCount(), 2);
139 vault.registrationComplete();
141 EXPECT_NE(watchdog.get(), nullptr);
142 EXPECT_EQ(watchdog.get(), SingletonDirectUsage<Watchdog>::get());
143 EXPECT_NE(watchdog.get(), named_watchdog.get());
144 EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
145 EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
147 vault.destroyInstances();
150 struct NamedUsageTag {};
151 template <typename T, typename Tag = detail::DefaultTag>
152 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
154 TEST(Singleton, NamedUsage) {
155 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
157 EXPECT_EQ(vault.registeredSingletonCount(), 0);
159 // Define two named Watchdog singletons and one unnamed singleton.
162 typedef detail::DefaultTag Watchdog3;
163 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
164 EXPECT_EQ(vault.registeredSingletonCount(), 1);
165 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
166 EXPECT_EQ(vault.registeredSingletonCount(), 2);
167 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
168 EXPECT_EQ(vault.registeredSingletonCount(), 3);
170 vault.registrationComplete();
172 // Verify our three singletons are distinct and non-nullptr.
173 Watchdog* s1 = SingletonNamedUsage<Watchdog, Watchdog1>::get();
174 EXPECT_EQ(s1, watchdog1_singleton.get());
175 Watchdog* s2 = SingletonNamedUsage<Watchdog, Watchdog2>::get();
176 EXPECT_EQ(s2, watchdog2_singleton.get());
178 Watchdog* s3 = SingletonNamedUsage<Watchdog, Watchdog3>::get();
179 EXPECT_EQ(s3, watchdog3_singleton.get());
183 // Verify the "default" singleton is the same as the DefaultTag-tagged
185 Watchdog* s4 = SingletonNamedUsage<Watchdog>::get();
186 EXPECT_EQ(s4, watchdog3_singleton.get());
188 vault.destroyInstances();
191 struct NaughtyUsageTag {};
192 template <typename T, typename Tag = detail::DefaultTag>
193 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
194 struct NaughtyUsageTag2 {};
195 template <typename T, typename Tag = detail::DefaultTag>
196 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
198 // Some pathological cases such as getting unregistered singletons,
199 // double registration, etc.
200 TEST(Singleton, NaughtyUsage) {
201 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
203 vault.registrationComplete();
206 EXPECT_DEATH(Singleton<Watchdog>::get(), "");
207 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::get(), "");
209 vault.destroyInstances();
211 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
213 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::get(), "");
214 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
216 // double registration
217 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
219 vault2.destroyInstances();
221 // double registration after destroy
222 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
226 struct SharedPtrUsageTag {};
227 template <typename T, typename Tag = detail::DefaultTag>
228 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
230 TEST(Singleton, SharedPtrUsage) {
231 struct WatchdogHolder {
234 LOG(ERROR) << "The following log message with stack trace is expected";
238 std::shared_ptr<Watchdog> watchdog;
241 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
243 EXPECT_EQ(vault.registeredSingletonCount(), 0);
244 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
245 EXPECT_EQ(vault.registeredSingletonCount(), 1);
247 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
248 EXPECT_EQ(vault.registeredSingletonCount(), 2);
251 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
253 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
255 vault.registrationComplete();
257 // Initilize holder singleton first, so that it's the last one to be
259 watchdog_holder_singleton.get();
261 Watchdog* s1 = SingletonSharedPtrUsage<Watchdog>::get();
262 EXPECT_NE(s1, nullptr);
264 Watchdog* s2 = SingletonSharedPtrUsage<Watchdog>::get();
265 EXPECT_NE(s2, nullptr);
269 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
271 auto shared_s1 = weak_s1.lock();
272 EXPECT_EQ(shared_s1.get(), s1);
273 EXPECT_EQ(shared_s1.use_count(), 2);
275 auto old_serial = shared_s1->serial_number;
279 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
280 auto locked = named_weak_s1.lock();
281 EXPECT_NE(locked.get(), shared_s1.get());
284 // We should release externally locked shared_ptr, otherwise it will be
286 watchdog_holder_singleton->watchdog = std::move(shared_s1);
288 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
290 auto start_time = std::chrono::steady_clock::now();
291 vault.destroyInstances();
292 auto duration = std::chrono::steady_clock::now() - start_time;
293 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
294 duration < std::chrono::seconds{6});
296 EXPECT_EQ(vault.registeredSingletonCount(), 4);
297 EXPECT_EQ(vault.livingSingletonCount(), 0);
299 EXPECT_TRUE(weak_s1.expired());
301 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
302 EXPECT_FALSE(empty_s1.lock());
304 vault.reenableInstances();
306 // Singleton should be re-created only after reenableInstances() was called.
307 Watchdog* new_s1 = SingletonSharedPtrUsage<Watchdog>::get();
308 // Track serial number rather than pointer since the memory could be
309 // re-used when we create new_s1.
310 EXPECT_NE(new_s1->serial_number, old_serial);
312 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
313 auto new_s1_shared = new_s1_weak.lock();
314 std::thread t([new_s1_shared]() mutable {
315 std::this_thread::sleep_for(std::chrono::seconds{2});
316 new_s1_shared.reset();
318 new_s1_shared.reset();
320 auto start_time = std::chrono::steady_clock::now();
321 vault.destroyInstances();
322 auto duration = std::chrono::steady_clock::now() - start_time;
323 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
324 duration < std::chrono::seconds{3});
326 EXPECT_TRUE(new_s1_weak.expired());
330 // Some classes to test singleton dependencies. NeedySingleton has a
331 // dependency on NeededSingleton, which happens during its
334 template <typename T, typename Tag = detail::DefaultTag>
335 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
337 struct NeededSingleton {};
338 struct NeedySingleton {
340 auto unused = SingletonNeedy<NeededSingleton>::get();
341 EXPECT_NE(unused, nullptr);
345 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
346 struct SelfNeedyTag {};
347 template <typename T, typename Tag = detail::DefaultTag>
348 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
350 struct SelfNeedySingleton {
351 SelfNeedySingleton() {
352 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::get();
353 EXPECT_NE(unused, nullptr);
357 TEST(Singleton, SingletonDependencies) {
358 SingletonNeedy<NeededSingleton> needed_singleton;
359 SingletonNeedy<NeedySingleton> needy_singleton;
360 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
362 needy_vault.registrationComplete();
364 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
365 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
367 auto needy = SingletonNeedy<NeedySingleton>::get();
368 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
370 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
371 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
373 self_needy_vault.registrationComplete();
374 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::get(); }(), "");
377 // A test to ensure multiple threads contending on singleton creation
378 // properly wait for creation rather than thinking it is a circular
380 class Slowpoke : public Watchdog {
382 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
385 struct ConcurrencyTag {};
386 template <typename T, typename Tag = detail::DefaultTag>
387 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
389 TEST(Singleton, SingletonConcurrency) {
390 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
391 SingletonConcurrency<Slowpoke> slowpoke_singleton;
392 vault.registrationComplete();
394 std::mutex gatekeeper;
396 auto func = [&gatekeeper]() {
399 auto unused = SingletonConcurrency<Slowpoke>::get();
402 EXPECT_EQ(vault.livingSingletonCount(), 0);
403 std::vector<std::thread> threads;
404 for (int i = 0; i < 100; ++i) {
405 threads.emplace_back(func);
407 // If circular dependency checks fail, the unlock would trigger a
408 // crash. Instead, it succeeds, and we have exactly one living
411 for (auto& t : threads) {
414 EXPECT_EQ(vault.livingSingletonCount(), 1);
417 struct ErrorConstructor {
418 static size_t constructCount_;
420 if ((constructCount_++) == 0) {
421 throw std::runtime_error("first time fails");
425 size_t ErrorConstructor::constructCount_(0);
427 struct CreationErrorTag {};
428 template <typename T, typename Tag = detail::DefaultTag>
429 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
431 TEST(Singleton, SingletonCreationError) {
432 auto& vault = *SingletonVault::singleton<CreationErrorTag>();
433 SingletonCreationError<ErrorConstructor> error_once_singleton;
435 // first time should error out
436 EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
438 // second time it'll work fine
439 error_once_singleton.get_weak().lock();
443 struct ConcurrencyStressTag {};
444 template <typename T, typename Tag = detail::DefaultTag>
445 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
447 TEST(Singleton, SingletonConcurrencyStress) {
448 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
449 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
451 std::vector<std::thread> ts;
452 for (size_t i = 0; i < 100; ++i) {
453 ts.emplace_back([&]() {
454 slowpoke_singleton.get_weak().lock();
458 for (size_t i = 0; i < 100; ++i) {
459 std::chrono::milliseconds d(20);
461 std::this_thread::sleep_for(d);
462 vault.destroyInstances();
463 std::this_thread::sleep_for(d);
464 vault.destroyInstances();
472 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
473 // singleton. Meyers are insanely fast, but (hopefully) Folly
474 // singletons are fast "enough."
475 int* getMeyersSingleton() {
476 static auto ret = new int(0);
480 int normal_singleton_value = 0;
481 int* getNormalSingleton() {
482 doNotOptimizeAway(&normal_singleton_value);
483 return &normal_singleton_value;
487 template <typename T, typename Tag = detail::DefaultTag>
488 using SingletonMock = Singleton <T, Tag, MockTag>;
490 // Verify that existing Singleton's can be overridden
491 // using the make_mock functionality.
492 TEST(Singleton, MockTest) {
493 auto& vault = *SingletonVault::singleton<MockTag>();
495 SingletonMock<Watchdog> watchdog_singleton;
496 vault.registrationComplete();
498 // Registring singletons after registrationComplete called works
499 // with make_mock (but not with Singleton ctor).
500 EXPECT_EQ(vault.registeredSingletonCount(), 1);
501 int serial_count_first = SingletonMock<Watchdog>::get()->serial_number;
503 // Override existing mock using make_mock.
504 SingletonMock<Watchdog>::make_mock();
506 EXPECT_EQ(vault.registeredSingletonCount(), 1);
507 int serial_count_mock = SingletonMock<Watchdog>::get()->serial_number;
509 // If serial_count value is the same, then singleton was not replaced.
510 EXPECT_NE(serial_count_first, serial_count_mock);
513 struct BenchmarkSingleton {
517 BENCHMARK(NormalSingleton, n) {
518 for (size_t i = 0; i < n; ++i) {
519 doNotOptimizeAway(getNormalSingleton());
523 BENCHMARK_RELATIVE(MeyersSingleton, n) {
524 for (size_t i = 0; i < n; ++i) {
525 doNotOptimizeAway(getMeyersSingleton());
529 struct BenchmarkTag {};
530 template <typename T, typename Tag = detail::DefaultTag>
531 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
536 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
537 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
539 BENCHMARK_RELATIVE(FollySingleton, n) {
540 for (size_t i = 0; i < n; ++i) {
541 doNotOptimizeAway(SingletonBenchmark<BenchmarkSingleton, GetTag>::get());
545 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
546 for (size_t i = 0; i < n; ++i) {
547 SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
551 int main(int argc, char* argv[]) {
552 testing::InitGoogleTest(&argc, argv);
553 google::InitGoogleLogging(argv[0]);
554 gflags::ParseCommandLineFlags(&argc, &argv, true);
556 SingletonVault::singleton()->registrationComplete();
558 auto ret = RUN_ALL_TESTS();
560 folly::runBenchmarksOnFlag();