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 // Exercise some basic codepaths ensuring registration order and
87 // destruction order happen as expected, that instances are created
88 // when expected, etc etc.
89 TEST(Singleton, BasicUsage) {
92 EXPECT_EQ(vault.registeredSingletonCount(), 0);
93 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
94 EXPECT_EQ(vault.registeredSingletonCount(), 1);
96 Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
97 EXPECT_EQ(vault.registeredSingletonCount(), 2);
99 vault.registrationComplete();
101 Watchdog* s1 = Singleton<Watchdog>::get(&vault);
102 EXPECT_NE(s1, nullptr);
104 Watchdog* s2 = Singleton<Watchdog>::get(&vault);
105 EXPECT_NE(s2, nullptr);
109 auto s3 = Singleton<ChildWatchdog>::get(&vault);
110 EXPECT_NE(s3, nullptr);
113 EXPECT_EQ(vault.registeredSingletonCount(), 2);
114 EXPECT_EQ(vault.livingSingletonCount(), 2);
116 vault.destroyInstances();
117 EXPECT_EQ(vault.registeredSingletonCount(), 2);
118 EXPECT_EQ(vault.livingSingletonCount(), 0);
121 TEST(Singleton, DirectUsage) {
122 SingletonVault vault;
124 EXPECT_EQ(vault.registeredSingletonCount(), 0);
126 // Verify we can get to the underlying singletons via directly using
127 // the singleton definition.
128 Singleton<Watchdog> watchdog(nullptr, nullptr, &vault);
130 Singleton<Watchdog, TestTag> named_watchdog(nullptr, nullptr, &vault);
131 EXPECT_EQ(vault.registeredSingletonCount(), 2);
132 vault.registrationComplete();
134 EXPECT_NE(watchdog.ptr(), nullptr);
135 EXPECT_EQ(watchdog.ptr(), Singleton<Watchdog>::get(&vault));
136 EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
137 EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
138 EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
141 TEST(Singleton, NamedUsage) {
142 SingletonVault vault;
144 EXPECT_EQ(vault.registeredSingletonCount(), 0);
146 // Define two named Watchdog singletons and one unnamed singleton.
149 typedef detail::DefaultTag Watchdog3;
150 Singleton<Watchdog, Watchdog1> watchdog1_singleton(nullptr, nullptr, &vault);
151 EXPECT_EQ(vault.registeredSingletonCount(), 1);
152 Singleton<Watchdog, Watchdog2> watchdog2_singleton(nullptr, nullptr, &vault);
153 EXPECT_EQ(vault.registeredSingletonCount(), 2);
154 Singleton<Watchdog, Watchdog3> watchdog3_singleton(nullptr, nullptr, &vault);
155 EXPECT_EQ(vault.registeredSingletonCount(), 3);
157 vault.registrationComplete();
159 // Verify our three singletons are distinct and non-nullptr.
160 Watchdog* s1 = Singleton<Watchdog, Watchdog1>::get(&vault);
161 EXPECT_EQ(s1, watchdog1_singleton.ptr());
162 Watchdog* s2 = Singleton<Watchdog, Watchdog2>::get(&vault);
163 EXPECT_EQ(s2, watchdog2_singleton.ptr());
165 Watchdog* s3 = Singleton<Watchdog, Watchdog3>::get(&vault);
166 EXPECT_EQ(s3, watchdog3_singleton.ptr());
170 // Verify the "default" singleton is the same as the DefaultTag-tagged
172 Watchdog* s4 = Singleton<Watchdog>::get(&vault);
173 EXPECT_EQ(s4, watchdog3_singleton.ptr());
176 // Some pathological cases such as getting unregistered singletons,
177 // double registration, etc.
178 TEST(Singleton, NaughtyUsage) {
179 SingletonVault vault(SingletonVault::Type::Strict);
180 vault.registrationComplete();
183 EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
184 EXPECT_THROW(Singleton<Watchdog>::get(&vault), std::out_of_range);
186 // Registring singletons after registrationComplete called.
187 EXPECT_THROW([&vault]() {
188 Singleton<Watchdog> watchdog_singleton(
189 nullptr, nullptr, &vault);
193 SingletonVault vault_2(SingletonVault::Type::Strict);
194 EXPECT_THROW(Singleton<Watchdog>::get(&vault_2), std::logic_error);
195 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault_2);
196 // double registration
197 EXPECT_THROW([&vault_2]() {
198 Singleton<Watchdog> watchdog_singleton(
199 nullptr, nullptr, &vault_2);
202 vault_2.destroyInstances();
203 // double registration after destroy
204 EXPECT_THROW([&vault_2]() {
205 Singleton<Watchdog> watchdog_singleton(
206 nullptr, nullptr, &vault_2);
211 TEST(Singleton, SharedPtrUsage) {
212 SingletonVault vault;
214 EXPECT_EQ(vault.registeredSingletonCount(), 0);
215 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
216 EXPECT_EQ(vault.registeredSingletonCount(), 1);
218 Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
219 EXPECT_EQ(vault.registeredSingletonCount(), 2);
222 Singleton<Watchdog, ATag> named_watchdog_singleton(nullptr, nullptr, &vault);
223 vault.registrationComplete();
225 Watchdog* s1 = Singleton<Watchdog>::get(&vault);
226 EXPECT_NE(s1, nullptr);
228 Watchdog* s2 = Singleton<Watchdog>::get(&vault);
229 EXPECT_NE(s2, nullptr);
233 auto weak_s1 = Singleton<Watchdog>::get_weak(&vault);
234 auto shared_s1 = weak_s1.lock();
235 EXPECT_EQ(shared_s1.get(), s1);
236 EXPECT_EQ(shared_s1.use_count(), 2);
239 auto named_weak_s1 = Singleton<Watchdog, ATag>::get_weak(&vault);
240 auto locked = named_weak_s1.lock();
241 EXPECT_NE(locked.get(), shared_s1.get());
244 LOG(ERROR) << "The following log message regarding shared_ptr is expected";
246 auto start_time = std::chrono::steady_clock::now();
247 vault.destroyInstances();
248 auto duration = std::chrono::steady_clock::now() - start_time;
249 EXPECT_TRUE(duration > std::chrono::seconds{4} &&
250 duration < std::chrono::seconds{6});
252 EXPECT_EQ(vault.registeredSingletonCount(), 3);
253 EXPECT_EQ(vault.livingSingletonCount(), 0);
255 EXPECT_EQ(shared_s1.use_count(), 1);
256 EXPECT_EQ(shared_s1.get(), s1);
258 auto locked_s1 = weak_s1.lock();
259 EXPECT_EQ(locked_s1.get(), s1);
260 EXPECT_EQ(shared_s1.use_count(), 2);
262 EXPECT_EQ(shared_s1.use_count(), 1);
264 // Track serial number rather than pointer since the memory could be
265 // re-used when we create new_s1.
266 auto old_serial = shared_s1->serial_number;
268 locked_s1 = weak_s1.lock();
269 EXPECT_TRUE(weak_s1.expired());
271 auto empty_s1 = Singleton<Watchdog>::get_weak(&vault);
272 EXPECT_FALSE(empty_s1.lock());
274 vault.reenableInstances();
276 // Singleton should be re-created only after reenableInstances() was called.
277 Watchdog* new_s1 = Singleton<Watchdog>::get(&vault);
278 EXPECT_NE(new_s1->serial_number, old_serial);
280 auto new_s1_weak = Singleton<Watchdog>::get_weak(&vault);
281 auto new_s1_shared = new_s1_weak.lock();
282 std::thread t([new_s1_shared]() mutable {
283 std::this_thread::sleep_for(std::chrono::seconds{2});
284 new_s1_shared.reset();
286 new_s1_shared.reset();
288 auto start_time = std::chrono::steady_clock::now();
289 vault.destroyInstances();
290 auto duration = std::chrono::steady_clock::now() - start_time;
291 EXPECT_TRUE(duration > std::chrono::seconds{1} &&
292 duration < std::chrono::seconds{3});
294 EXPECT_TRUE(new_s1_weak.expired());
298 // Some classes to test singleton dependencies. NeedySingleton has a
299 // dependency on NeededSingleton, which happens during its
301 SingletonVault needy_vault;
303 struct NeededSingleton {};
304 struct NeedySingleton {
306 auto unused = Singleton<NeededSingleton>::get(&needy_vault);
307 EXPECT_NE(unused, nullptr);
311 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
312 SingletonVault self_needy_vault;
313 struct SelfNeedySingleton {
314 SelfNeedySingleton() {
315 auto unused = Singleton<SelfNeedySingleton>::get(&self_needy_vault);
316 EXPECT_NE(unused, nullptr);
320 TEST(Singleton, SingletonDependencies) {
321 Singleton<NeededSingleton> needed_singleton(nullptr, nullptr, &needy_vault);
322 Singleton<NeedySingleton> needy_singleton(nullptr, nullptr, &needy_vault);
323 needy_vault.registrationComplete();
325 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
326 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
328 auto needy = Singleton<NeedySingleton>::get(&needy_vault);
329 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
331 Singleton<SelfNeedySingleton> self_needy_singleton(
332 nullptr, nullptr, &self_needy_vault);
333 self_needy_vault.registrationComplete();
335 Singleton<SelfNeedySingleton>::get(&self_needy_vault);
340 // A test to ensure multiple threads contending on singleton creation
341 // properly wait for creation rather than thinking it is a circular
343 class Slowpoke : public Watchdog {
345 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
348 TEST(Singleton, SingletonConcurrency) {
349 SingletonVault vault;
350 Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
351 vault.registrationComplete();
353 std::mutex gatekeeper;
355 auto func = [&vault, &gatekeeper]() {
358 auto unused = Singleton<Slowpoke>::get(&vault);
361 EXPECT_EQ(vault.livingSingletonCount(), 0);
362 std::vector<std::thread> threads;
363 for (int i = 0; i < 100; ++i) {
364 threads.emplace_back(func);
366 // If circular dependency checks fail, the unlock would trigger a
367 // crash. Instead, it succeeds, and we have exactly one living
370 for (auto& t : threads) {
373 EXPECT_EQ(vault.livingSingletonCount(), 1);
376 TEST(Singleton, SingletonConcurrencyStress) {
377 SingletonVault vault;
378 Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
380 std::vector<std::thread> ts;
381 for (size_t i = 0; i < 100; ++i) {
382 ts.emplace_back([&]() {
383 slowpoke_singleton.get_weak(&vault).lock();
387 for (size_t i = 0; i < 100; ++i) {
388 std::chrono::milliseconds d(20);
390 std::this_thread::sleep_for(d);
391 vault.destroyInstances();
392 std::this_thread::sleep_for(d);
393 vault.destroyInstances();
401 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
402 // singleton. Meyers are insanely fast, but (hopefully) Folly
403 // singletons are fast "enough."
404 int* getMeyersSingleton() {
405 static auto ret = new int(0);
409 int normal_singleton_value = 0;
410 int* getNormalSingleton() {
411 doNotOptimizeAway(&normal_singleton_value);
412 return &normal_singleton_value;
415 // Verify that existing Singleton's can be overridden
416 // using the make_mock functionality.
417 TEST(Singleton, make_mock) {
418 SingletonVault vault(SingletonVault::Type::Strict);
419 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
420 vault.registrationComplete();
422 // Registring singletons after registrationComplete called works
423 // with make_mock (but not with Singleton ctor).
424 EXPECT_EQ(vault.registeredSingletonCount(), 1);
425 int serial_count_first = Singleton<Watchdog>::get(&vault)->serial_number;
427 // Override existing mock using make_mock.
428 Singleton<Watchdog>::make_mock(nullptr, nullptr, &vault);
430 EXPECT_EQ(vault.registeredSingletonCount(), 1);
431 int serial_count_mock = Singleton<Watchdog>::get(&vault)->serial_number;
433 // If serial_count value is the same, then singleton was not replaced.
434 EXPECT_NE(serial_count_first, serial_count_mock);
437 struct BenchmarkSingleton {
441 BENCHMARK(NormalSingleton, n) {
442 for (size_t i = 0; i < n; ++i) {
443 doNotOptimizeAway(getNormalSingleton());
447 BENCHMARK_RELATIVE(MeyersSingleton, n) {
448 for (size_t i = 0; i < n; ++i) {
449 doNotOptimizeAway(getMeyersSingleton());
453 BENCHMARK_RELATIVE(FollySingletonSlow, n) {
454 SingletonVault benchmark_vault;
455 Singleton<BenchmarkSingleton> benchmark_singleton(
456 nullptr, nullptr, &benchmark_vault);
457 benchmark_vault.registrationComplete();
459 for (size_t i = 0; i < n; ++i) {
460 doNotOptimizeAway(Singleton<BenchmarkSingleton>::get(&benchmark_vault));
464 BENCHMARK_RELATIVE(FollySingletonFast, n) {
465 SingletonVault benchmark_vault;
466 Singleton<BenchmarkSingleton> benchmark_singleton(
467 nullptr, nullptr, &benchmark_vault);
468 benchmark_vault.registrationComplete();
470 for (size_t i = 0; i < n; ++i) {
471 doNotOptimizeAway(benchmark_singleton.get_fast());
475 BENCHMARK_RELATIVE(FollySingletonFastWeak, n) {
476 SingletonVault benchmark_vault;
477 Singleton<BenchmarkSingleton> benchmark_singleton(
478 nullptr, nullptr, &benchmark_vault);
479 benchmark_vault.registrationComplete();
481 for (size_t i = 0; i < n; ++i) {
482 benchmark_singleton.get_weak_fast();
486 int main(int argc, char* argv[]) {
487 testing::InitGoogleTest(&argc, argv);
488 google::InitGoogleLogging(argv[0]);
489 google::ParseCommandLineFlags(&argc, &argv, true);
491 SingletonVault::singleton()->registrationComplete();
493 auto ret = RUN_ALL_TESTS();
495 folly::runBenchmarksOnFlag();