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);
72 std::shared_ptr<GlobalWatchdog> wd1 = Singleton<GlobalWatchdog>::try_get();
73 EXPECT_NE(wd1, nullptr);
74 EXPECT_EQ(Watchdog::creation_order.size(), 1);
75 std::shared_ptr<GlobalWatchdog> wd2 = Singleton<GlobalWatchdog>::try_get();
76 EXPECT_NE(wd2, nullptr);
77 EXPECT_EQ(wd1.get(), wd2.get());
78 EXPECT_EQ(Watchdog::creation_order.size(), 1);
81 SingletonVault::singleton()->destroyInstances();
82 EXPECT_EQ(Watchdog::creation_order.size(), 0);
85 TEST(Singleton, MissingSingleton) {
86 EXPECT_DEATH([]() { auto u = Singleton<UnregisteredWatchdog>::try_get(); }(),
90 struct BasicUsageTag {};
91 template <typename T, typename Tag = detail::DefaultTag>
92 using SingletonBasicUsage = Singleton <T, Tag, BasicUsageTag>;
94 // Exercise some basic codepaths ensuring registration order and
95 // destruction order happen as expected, that instances are created
96 // when expected, etc etc.
97 TEST(Singleton, BasicUsage) {
98 auto& vault = *SingletonVault::singleton<BasicUsageTag>();
100 EXPECT_EQ(vault.registeredSingletonCount(), 0);
101 SingletonBasicUsage<Watchdog> watchdog_singleton;
102 EXPECT_EQ(vault.registeredSingletonCount(), 1);
104 SingletonBasicUsage<ChildWatchdog> child_watchdog_singleton;
105 EXPECT_EQ(vault.registeredSingletonCount(), 2);
107 vault.registrationComplete();
109 // limit a scope to release references so we can destroy them later
111 std::shared_ptr<Watchdog> s1 = SingletonBasicUsage<Watchdog>::try_get();
112 EXPECT_NE(s1, nullptr);
114 std::shared_ptr<Watchdog> s2 = SingletonBasicUsage<Watchdog>::try_get();
115 EXPECT_NE(s2, nullptr);
119 std::shared_ptr<ChildWatchdog> s3 =
120 SingletonBasicUsage<ChildWatchdog>::try_get();
121 EXPECT_NE(s3, nullptr);
124 EXPECT_EQ(vault.registeredSingletonCount(), 2);
125 EXPECT_EQ(vault.livingSingletonCount(), 2);
128 vault.destroyInstances();
129 EXPECT_EQ(vault.registeredSingletonCount(), 2);
130 EXPECT_EQ(vault.livingSingletonCount(), 0);
133 struct DirectUsageTag {};
134 template <typename T, typename Tag = detail::DefaultTag>
135 using SingletonDirectUsage = Singleton <T, Tag, DirectUsageTag>;
137 TEST(Singleton, DirectUsage) {
138 auto& vault = *SingletonVault::singleton<DirectUsageTag>();
140 EXPECT_EQ(vault.registeredSingletonCount(), 0);
142 // Verify we can get to the underlying singletons via directly using
143 // the singleton definition.
144 SingletonDirectUsage<Watchdog> watchdog;
146 SingletonDirectUsage<Watchdog, TestTag> named_watchdog;
147 EXPECT_EQ(vault.registeredSingletonCount(), 2);
148 vault.registrationComplete();
150 EXPECT_NE(watchdog.try_get(), nullptr);
151 EXPECT_EQ(watchdog.try_get(), SingletonDirectUsage<Watchdog>::try_get());
152 EXPECT_NE(watchdog.try_get(), named_watchdog.try_get());
153 EXPECT_EQ(watchdog.try_get()->livingWatchdogCount(), 2);
155 vault.destroyInstances();
158 struct NamedUsageTag {};
159 template <typename T, typename Tag = detail::DefaultTag>
160 using SingletonNamedUsage = Singleton <T, Tag, NamedUsageTag>;
162 TEST(Singleton, NamedUsage) {
163 auto& vault = *SingletonVault::singleton<NamedUsageTag>();
165 EXPECT_EQ(vault.registeredSingletonCount(), 0);
167 // Define two named Watchdog singletons and one unnamed singleton.
170 typedef detail::DefaultTag Watchdog3;
171 SingletonNamedUsage<Watchdog, Watchdog1> watchdog1_singleton;
172 EXPECT_EQ(vault.registeredSingletonCount(), 1);
173 SingletonNamedUsage<Watchdog, Watchdog2> watchdog2_singleton;
174 EXPECT_EQ(vault.registeredSingletonCount(), 2);
175 SingletonNamedUsage<Watchdog, Watchdog3> watchdog3_singleton;
176 EXPECT_EQ(vault.registeredSingletonCount(), 3);
178 vault.registrationComplete();
180 // Verify our three singletons are distinct and non-nullptr.
181 auto s1 = SingletonNamedUsage<Watchdog, Watchdog1>::try_get();
182 EXPECT_EQ(s1, watchdog1_singleton.try_get());
183 auto s2 = SingletonNamedUsage<Watchdog, Watchdog2>::try_get();
184 EXPECT_EQ(s2, watchdog2_singleton.try_get());
186 auto s3 = SingletonNamedUsage<Watchdog, Watchdog3>::try_get();
187 EXPECT_EQ(s3, watchdog3_singleton.try_get());
191 // Verify the "default" singleton is the same as the DefaultTag-tagged
193 auto s4 = SingletonNamedUsage<Watchdog>::try_get();
194 EXPECT_EQ(s4, watchdog3_singleton.try_get());
197 vault.destroyInstances();
200 struct NaughtyUsageTag {};
201 template <typename T, typename Tag = detail::DefaultTag>
202 using SingletonNaughtyUsage = Singleton <T, Tag, NaughtyUsageTag>;
203 struct NaughtyUsageTag2 {};
204 template <typename T, typename Tag = detail::DefaultTag>
205 using SingletonNaughtyUsage2 = Singleton <T, Tag, NaughtyUsageTag2>;
207 // Some pathological cases such as getting unregistered singletons,
208 // double registration, etc.
209 TEST(Singleton, NaughtyUsage) {
210 auto& vault = *SingletonVault::singleton<NaughtyUsageTag>();
212 vault.registrationComplete();
215 EXPECT_DEATH(Singleton<Watchdog>::try_get(), "");
216 EXPECT_DEATH(SingletonNaughtyUsage<Watchdog>::try_get(), "");
218 vault.destroyInstances();
220 auto& vault2 = *SingletonVault::singleton<NaughtyUsageTag2>();
222 EXPECT_DEATH(SingletonNaughtyUsage2<Watchdog>::try_get(), "");
223 SingletonNaughtyUsage2<Watchdog> watchdog_singleton;
225 // double registration
226 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
228 vault2.destroyInstances();
230 // double registration after destroy
231 EXPECT_DEATH([]() { SingletonNaughtyUsage2<Watchdog> watchdog_singleton; }(),
235 struct SharedPtrUsageTag {};
236 template <typename T, typename Tag = detail::DefaultTag>
237 using SingletonSharedPtrUsage = Singleton <T, Tag, SharedPtrUsageTag>;
239 // TODO (anob): revisit this test
240 TEST(Singleton, SharedPtrUsage) {
241 struct WatchdogHolder {
244 LOG(ERROR) << "The following log message with stack trace is expected";
248 std::shared_ptr<Watchdog> watchdog;
251 auto& vault = *SingletonVault::singleton<SharedPtrUsageTag>();
253 EXPECT_EQ(vault.registeredSingletonCount(), 0);
254 SingletonSharedPtrUsage<Watchdog> watchdog_singleton;
255 EXPECT_EQ(vault.registeredSingletonCount(), 1);
257 SingletonSharedPtrUsage<ChildWatchdog> child_watchdog_singleton;
258 EXPECT_EQ(vault.registeredSingletonCount(), 2);
261 SingletonSharedPtrUsage<Watchdog, ATag> named_watchdog_singleton;
263 SingletonSharedPtrUsage<WatchdogHolder> watchdog_holder_singleton;
265 vault.registrationComplete();
267 // Initilize holder singleton first, so that it's the last one to be
269 watchdog_holder_singleton.try_get();
271 auto s1 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
272 EXPECT_NE(s1, nullptr);
274 auto s2 = SingletonSharedPtrUsage<Watchdog>::try_get().get();
275 EXPECT_NE(s2, nullptr);
279 auto weak_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
281 auto shared_s1 = weak_s1.lock();
282 EXPECT_EQ(shared_s1.get(), s1);
283 EXPECT_EQ(shared_s1.use_count(), 2);
285 auto old_serial = shared_s1->serial_number;
289 SingletonSharedPtrUsage<Watchdog, ATag>::get_weak();
290 auto locked = named_weak_s1.lock();
291 EXPECT_NE(locked.get(), shared_s1.get());
294 // We should release externally locked shared_ptr, otherwise it will be
296 watchdog_holder_singleton.try_get()->watchdog = std::move(shared_s1);
298 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
300 auto start_time = std::chrono::steady_clock::now();
301 vault.destroyInstances();
302 auto duration = std::chrono::steady_clock::now() - start_time;
303 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
304 duration < std::chrono::seconds{6});
306 EXPECT_EQ(vault.registeredSingletonCount(), 4);
307 EXPECT_EQ(vault.livingSingletonCount(), 0);
309 EXPECT_TRUE(weak_s1.expired());
311 auto empty_s1 = SingletonSharedPtrUsage<Watchdog>::get_weak();
312 EXPECT_FALSE(empty_s1.lock());
314 vault.reenableInstances();
317 // Singleton should be re-created only after reenableInstances() was called.
318 auto new_s1 = SingletonSharedPtrUsage<Watchdog>::try_get();
319 // Track serial number rather than pointer since the memory could be
320 // re-used when we create new_s1.
321 EXPECT_NE(new_s1->serial_number, old_serial);
324 auto new_s1_weak = SingletonSharedPtrUsage<Watchdog>::get_weak();
325 auto new_s1_shared = new_s1_weak.lock();
326 std::thread t([new_s1_shared]() mutable {
327 std::this_thread::sleep_for(std::chrono::seconds{2});
328 new_s1_shared.reset();
330 new_s1_shared.reset();
332 auto start_time = std::chrono::steady_clock::now();
333 vault.destroyInstances();
334 auto duration = std::chrono::steady_clock::now() - start_time;
335 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
336 duration < std::chrono::seconds{3});
338 EXPECT_TRUE(new_s1_weak.expired());
342 // Some classes to test singleton dependencies. NeedySingleton has a
343 // dependency on NeededSingleton, which happens during its
346 template <typename T, typename Tag = detail::DefaultTag>
347 using SingletonNeedy = Singleton <T, Tag, NeedyTag>;
349 struct NeededSingleton {};
350 struct NeedySingleton {
352 auto unused = SingletonNeedy<NeededSingleton>::try_get();
353 EXPECT_NE(unused, nullptr);
357 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
358 struct SelfNeedyTag {};
359 template <typename T, typename Tag = detail::DefaultTag>
360 using SingletonSelfNeedy = Singleton <T, Tag, SelfNeedyTag>;
362 struct SelfNeedySingleton {
363 SelfNeedySingleton() {
364 auto unused = SingletonSelfNeedy<SelfNeedySingleton>::try_get();
365 EXPECT_NE(unused, nullptr);
369 TEST(Singleton, SingletonDependencies) {
370 SingletonNeedy<NeededSingleton> needed_singleton;
371 SingletonNeedy<NeedySingleton> needy_singleton;
372 auto& needy_vault = *SingletonVault::singleton<NeedyTag>();
374 needy_vault.registrationComplete();
376 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
377 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
379 auto needy = SingletonNeedy<NeedySingleton>::try_get();
380 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
382 SingletonSelfNeedy<SelfNeedySingleton> self_needy_singleton;
383 auto& self_needy_vault = *SingletonVault::singleton<SelfNeedyTag>();
385 self_needy_vault.registrationComplete();
386 EXPECT_DEATH([]() { SingletonSelfNeedy<SelfNeedySingleton>::try_get(); }(),
390 // A test to ensure multiple threads contending on singleton creation
391 // properly wait for creation rather than thinking it is a circular
393 class Slowpoke : public Watchdog {
395 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
398 struct ConcurrencyTag {};
399 template <typename T, typename Tag = detail::DefaultTag>
400 using SingletonConcurrency = Singleton <T, Tag, ConcurrencyTag>;
402 TEST(Singleton, SingletonConcurrency) {
403 auto& vault = *SingletonVault::singleton<ConcurrencyTag>();
404 SingletonConcurrency<Slowpoke> slowpoke_singleton;
405 vault.registrationComplete();
407 std::mutex gatekeeper;
409 auto func = [&gatekeeper]() {
412 auto unused = SingletonConcurrency<Slowpoke>::try_get();
415 EXPECT_EQ(vault.livingSingletonCount(), 0);
416 std::vector<std::thread> threads;
417 for (int i = 0; i < 100; ++i) {
418 threads.emplace_back(func);
420 // If circular dependency checks fail, the unlock would trigger a
421 // crash. Instead, it succeeds, and we have exactly one living
424 for (auto& t : threads) {
427 EXPECT_EQ(vault.livingSingletonCount(), 1);
430 struct ErrorConstructor {
431 static size_t constructCount_;
433 if ((constructCount_++) == 0) {
434 throw std::runtime_error("first time fails");
438 size_t ErrorConstructor::constructCount_(0);
440 struct CreationErrorTag {};
441 template <typename T, typename Tag = detail::DefaultTag>
442 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
444 TEST(Singleton, SingletonCreationError) {
445 auto& vault = *SingletonVault::singleton<CreationErrorTag>();
446 SingletonCreationError<ErrorConstructor> error_once_singleton;
448 // first time should error out
449 EXPECT_THROW(error_once_singleton.get_weak().lock(), std::runtime_error);
451 // second time it'll work fine
452 error_once_singleton.get_weak().lock();
456 struct ConcurrencyStressTag {};
457 template <typename T, typename Tag = detail::DefaultTag>
458 using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
460 TEST(Singleton, SingletonConcurrencyStress) {
461 auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
462 SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
464 std::vector<std::thread> ts;
465 for (size_t i = 0; i < 100; ++i) {
466 ts.emplace_back([&]() {
467 slowpoke_singleton.get_weak().lock();
471 for (size_t i = 0; i < 100; ++i) {
472 std::chrono::milliseconds d(20);
474 std::this_thread::sleep_for(d);
475 vault.destroyInstances();
476 std::this_thread::sleep_for(d);
477 vault.destroyInstances();
485 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
486 // singleton. Meyers are insanely fast, but (hopefully) Folly
487 // singletons are fast "enough."
488 int* getMeyersSingleton() {
489 static auto ret = new int(0);
493 int normal_singleton_value = 0;
494 int* getNormalSingleton() {
495 doNotOptimizeAway(&normal_singleton_value);
496 return &normal_singleton_value;
500 template <typename T, typename Tag = detail::DefaultTag>
501 using SingletonMock = Singleton <T, Tag, MockTag>;
503 // Verify that existing Singleton's can be overridden
504 // using the make_mock functionality.
505 TEST(Singleton, MockTest) {
506 auto& vault = *SingletonVault::singleton<MockTag>();
508 SingletonMock<Watchdog> watchdog_singleton;
509 vault.registrationComplete();
511 // Registring singletons after registrationComplete called works
512 // with make_mock (but not with Singleton ctor).
513 EXPECT_EQ(vault.registeredSingletonCount(), 1);
514 int serial_count_first = SingletonMock<Watchdog>::try_get()->serial_number;
516 // Override existing mock using make_mock.
517 SingletonMock<Watchdog>::make_mock();
519 EXPECT_EQ(vault.registeredSingletonCount(), 1);
520 int serial_count_mock = SingletonMock<Watchdog>::try_get()->serial_number;
522 // If serial_count value is the same, then singleton was not replaced.
523 EXPECT_NE(serial_count_first, serial_count_mock);
526 struct BenchmarkSingleton {
530 BENCHMARK(NormalSingleton, n) {
531 for (size_t i = 0; i < n; ++i) {
532 doNotOptimizeAway(getNormalSingleton());
536 BENCHMARK_RELATIVE(MeyersSingleton, n) {
537 for (size_t i = 0; i < n; ++i) {
538 doNotOptimizeAway(getMeyersSingleton());
542 struct BenchmarkTag {};
543 template <typename T, typename Tag = detail::DefaultTag>
544 using SingletonBenchmark = Singleton <T, Tag, BenchmarkTag>;
549 SingletonBenchmark<BenchmarkSingleton, GetTag> benchmark_singleton_get;
550 SingletonBenchmark<BenchmarkSingleton, GetWeakTag> benchmark_singleton_get_weak;
552 BENCHMARK_RELATIVE(FollySingleton, n) {
553 for (size_t i = 0; i < n; ++i) {
554 SingletonBenchmark<BenchmarkSingleton, GetTag>::try_get();
558 BENCHMARK_RELATIVE(FollySingletonWeak, n) {
559 for (size_t i = 0; i < n; ++i) {
560 SingletonBenchmark<BenchmarkSingleton, GetWeakTag>::get_weak();
564 int main(int argc, char* argv[]) {
565 testing::InitGoogleTest(&argc, argv);
566 google::InitGoogleLogging(argv[0]);
567 gflags::ParseCommandLineFlags(&argc, &argv, true);
569 SingletonVault::singleton()->registrationComplete();
571 auto ret = RUN_ALL_TESTS();
573 folly::runBenchmarksOnFlag();