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);
129 Singleton<Watchdog> named_watchdog("named", nullptr, nullptr, &vault);
130 EXPECT_EQ(vault.registeredSingletonCount(), 2);
131 vault.registrationComplete();
133 EXPECT_NE(watchdog.ptr(), nullptr);
134 EXPECT_EQ(watchdog.ptr(), Singleton<Watchdog>::get(&vault));
135 EXPECT_NE(watchdog.ptr(), named_watchdog.ptr());
136 EXPECT_EQ(watchdog->livingWatchdogCount(), 2);
137 EXPECT_EQ((*watchdog).livingWatchdogCount(), 2);
140 TEST(Singleton, NamedUsage) {
141 SingletonVault vault;
143 EXPECT_EQ(vault.registeredSingletonCount(), 0);
145 // Define two named Watchdog singletons and one unnamed singleton.
146 Singleton<Watchdog> watchdog1_singleton(
147 "watchdog1", nullptr, nullptr, &vault);
148 EXPECT_EQ(vault.registeredSingletonCount(), 1);
149 Singleton<Watchdog> watchdog2_singleton(
150 "watchdog2", nullptr, nullptr, &vault);
151 EXPECT_EQ(vault.registeredSingletonCount(), 2);
152 Singleton<Watchdog> watchdog3_singleton(nullptr, nullptr, &vault);
153 EXPECT_EQ(vault.registeredSingletonCount(), 3);
155 vault.registrationComplete();
157 // Verify our three singletons are distinct and non-nullptr.
158 Watchdog* s1 = Singleton<Watchdog>::get("watchdog1", &vault);
159 EXPECT_EQ(s1, watchdog1_singleton.ptr());
160 Watchdog* s2 = Singleton<Watchdog>::get("watchdog2", &vault);
161 EXPECT_EQ(s2, watchdog2_singleton.ptr());
163 Watchdog* s3 = Singleton<Watchdog>::get(&vault);
164 EXPECT_EQ(s3, watchdog3_singleton.ptr());
168 // Verify the "default" singleton is the same as the empty string
170 Watchdog* s4 = Singleton<Watchdog>::get("", &vault);
171 EXPECT_EQ(s4, watchdog3_singleton.ptr());
174 // Some pathological cases such as getting unregistered singletons,
175 // double registration, etc.
176 TEST(Singleton, NaughtyUsage) {
177 SingletonVault vault(SingletonVault::Type::Strict);
178 vault.registrationComplete();
181 EXPECT_THROW(Singleton<Watchdog>::get(), std::out_of_range);
182 EXPECT_THROW(Singleton<Watchdog>::get(&vault), std::out_of_range);
184 // Registring singletons after registrationComplete called.
185 EXPECT_THROW([&vault]() {
186 Singleton<Watchdog> watchdog_singleton(
187 nullptr, nullptr, &vault);
191 SingletonVault vault_2(SingletonVault::Type::Strict);
192 EXPECT_THROW(Singleton<Watchdog>::get(&vault_2), std::logic_error);
193 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault_2);
194 // double registration
195 EXPECT_THROW([&vault_2]() {
196 Singleton<Watchdog> watchdog_singleton(
197 nullptr, nullptr, &vault_2);
200 vault_2.destroyInstances();
201 // double registration after destroy
202 EXPECT_THROW([&vault_2]() {
203 Singleton<Watchdog> watchdog_singleton(
204 nullptr, nullptr, &vault_2);
209 TEST(Singleton, SharedPtrUsage) {
210 SingletonVault vault;
212 EXPECT_EQ(vault.registeredSingletonCount(), 0);
213 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
214 EXPECT_EQ(vault.registeredSingletonCount(), 1);
216 Singleton<ChildWatchdog> child_watchdog_singleton(nullptr, nullptr, &vault);
217 EXPECT_EQ(vault.registeredSingletonCount(), 2);
219 Singleton<Watchdog> named_watchdog_singleton(
220 "a_name", nullptr, nullptr, &vault);
221 vault.registrationComplete();
223 Watchdog* s1 = Singleton<Watchdog>::get(&vault);
224 EXPECT_NE(s1, nullptr);
226 Watchdog* s2 = Singleton<Watchdog>::get(&vault);
227 EXPECT_NE(s2, nullptr);
231 auto weak_s1 = Singleton<Watchdog>::get_weak(&vault);
232 auto shared_s1 = weak_s1.lock();
233 EXPECT_EQ(shared_s1.get(), s1);
234 EXPECT_EQ(shared_s1.use_count(), 2);
237 auto named_weak_s1 = Singleton<Watchdog>::get_weak("a_name", &vault);
238 auto locked = named_weak_s1.lock();
239 EXPECT_NE(locked.get(), shared_s1.get());
242 LOG(ERROR) << "The following log message regarding ref counts is expected";
243 vault.destroyInstances();
244 EXPECT_EQ(vault.registeredSingletonCount(), 3);
245 EXPECT_EQ(vault.livingSingletonCount(), 0);
247 EXPECT_EQ(shared_s1.use_count(), 1);
248 EXPECT_EQ(shared_s1.get(), s1);
250 auto locked_s1 = weak_s1.lock();
251 EXPECT_EQ(locked_s1.get(), s1);
252 EXPECT_EQ(shared_s1.use_count(), 2);
254 EXPECT_EQ(shared_s1.use_count(), 1);
256 // Track serial number rather than pointer since the memory could be
257 // re-used when we create new_s1.
258 auto old_serial = shared_s1->serial_number;
260 locked_s1 = weak_s1.lock();
261 EXPECT_TRUE(weak_s1.expired());
263 auto empty_s1 = Singleton<Watchdog>::get_weak(&vault);
264 EXPECT_FALSE(empty_s1.lock());
266 vault.reenableInstances();
268 // Singleton should be re-created only after reenableInstances() was called.
269 Watchdog* new_s1 = Singleton<Watchdog>::get(&vault);
270 EXPECT_NE(new_s1->serial_number, old_serial);
273 // Some classes to test singleton dependencies. NeedySingleton has a
274 // dependency on NeededSingleton, which happens during its
276 SingletonVault needy_vault;
278 struct NeededSingleton {};
279 struct NeedySingleton {
281 auto unused = Singleton<NeededSingleton>::get(&needy_vault);
282 EXPECT_NE(unused, nullptr);
286 // Ensure circular dependencies fail -- a singleton that needs itself, whoops.
287 SingletonVault self_needy_vault;
288 struct SelfNeedySingleton {
289 SelfNeedySingleton() {
290 auto unused = Singleton<SelfNeedySingleton>::get(&self_needy_vault);
291 EXPECT_NE(unused, nullptr);
295 TEST(Singleton, SingletonDependencies) {
296 Singleton<NeededSingleton> needed_singleton(nullptr, nullptr, &needy_vault);
297 Singleton<NeedySingleton> needy_singleton(nullptr, nullptr, &needy_vault);
298 needy_vault.registrationComplete();
300 EXPECT_EQ(needy_vault.registeredSingletonCount(), 2);
301 EXPECT_EQ(needy_vault.livingSingletonCount(), 0);
303 auto needy = Singleton<NeedySingleton>::get(&needy_vault);
304 EXPECT_EQ(needy_vault.livingSingletonCount(), 2);
306 Singleton<SelfNeedySingleton> self_needy_singleton(
307 nullptr, nullptr, &self_needy_vault);
308 self_needy_vault.registrationComplete();
310 Singleton<SelfNeedySingleton>::get(&self_needy_vault);
315 // A test to ensure multiple threads contending on singleton creation
316 // properly wait for creation rather than thinking it is a circular
318 class Slowpoke : public Watchdog {
320 Slowpoke() { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
323 TEST(Singleton, SingletonConcurrency) {
324 SingletonVault vault;
325 Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
326 vault.registrationComplete();
328 std::mutex gatekeeper;
330 auto func = [&vault, &gatekeeper]() {
333 auto unused = Singleton<Slowpoke>::get(&vault);
336 EXPECT_EQ(vault.livingSingletonCount(), 0);
337 std::vector<std::thread> threads;
338 for (int i = 0; i < 100; ++i) {
339 threads.emplace_back(func);
341 // If circular dependency checks fail, the unlock would trigger a
342 // crash. Instead, it succeeds, and we have exactly one living
345 for (auto& t : threads) {
348 EXPECT_EQ(vault.livingSingletonCount(), 1);
351 TEST(Singleton, SingletonConcurrencyStress) {
352 SingletonVault vault;
353 Singleton<Slowpoke> slowpoke_singleton(nullptr, nullptr, &vault);
355 std::vector<std::thread> ts;
356 for (size_t i = 0; i < 100; ++i) {
357 ts.emplace_back([&]() {
358 slowpoke_singleton.get_weak(&vault).lock();
362 for (size_t i = 0; i < 100; ++i) {
363 std::chrono::milliseconds d(20);
365 std::this_thread::sleep_for(d);
366 vault.destroyInstances();
367 std::this_thread::sleep_for(d);
368 vault.destroyInstances();
376 // Benchmarking a normal singleton vs a Meyers singleton vs a Folly
377 // singleton. Meyers are insanely fast, but (hopefully) Folly
378 // singletons are fast "enough."
379 int* getMeyersSingleton() {
380 static auto ret = new int(0);
384 int normal_singleton_value = 0;
385 int* getNormalSingleton() {
386 doNotOptimizeAway(&normal_singleton_value);
387 return &normal_singleton_value;
390 // Verify that existing Singleton's can be overridden
391 // using the make_mock functionality.
392 TEST(Singleton, make_mock) {
393 SingletonVault vault(SingletonVault::Type::Strict);
394 Singleton<Watchdog> watchdog_singleton(nullptr, nullptr, &vault);
395 vault.registrationComplete();
397 // Registring singletons after registrationComplete called works
398 // with make_mock (but not with Singleton ctor).
399 EXPECT_EQ(vault.registeredSingletonCount(), 1);
400 int serial_count_first = Singleton<Watchdog>::get(&vault)->serial_number;
402 // Override existing mock using make_mock.
403 Singleton<Watchdog>::make_mock(nullptr, nullptr, &vault);
405 EXPECT_EQ(vault.registeredSingletonCount(), 1);
406 int serial_count_mock = Singleton<Watchdog>::get(&vault)->serial_number;
408 // If serial_count value is the same, then singleton was not replaced.
409 EXPECT_NE(serial_count_first, serial_count_mock);
412 struct BenchmarkSingleton {
416 BENCHMARK(NormalSingleton, n) {
417 for (size_t i = 0; i < n; ++i) {
418 doNotOptimizeAway(getNormalSingleton());
422 BENCHMARK_RELATIVE(MeyersSingleton, n) {
423 for (size_t i = 0; i < n; ++i) {
424 doNotOptimizeAway(getMeyersSingleton());
428 BENCHMARK_RELATIVE(FollySingletonSlow, n) {
429 SingletonVault benchmark_vault;
430 Singleton<BenchmarkSingleton> benchmark_singleton(
431 nullptr, nullptr, &benchmark_vault);
432 benchmark_vault.registrationComplete();
434 for (size_t i = 0; i < n; ++i) {
435 doNotOptimizeAway(Singleton<BenchmarkSingleton>::get(&benchmark_vault));
439 BENCHMARK_RELATIVE(FollySingletonFast, n) {
440 SingletonVault benchmark_vault;
441 Singleton<BenchmarkSingleton> benchmark_singleton(
442 nullptr, nullptr, &benchmark_vault);
443 benchmark_vault.registrationComplete();
445 for (size_t i = 0; i < n; ++i) {
446 doNotOptimizeAway(benchmark_singleton.get_fast());
450 BENCHMARK_RELATIVE(FollySingletonFastWeak, n) {
451 SingletonVault benchmark_vault;
452 Singleton<BenchmarkSingleton> benchmark_singleton(
453 nullptr, nullptr, &benchmark_vault);
454 benchmark_vault.registrationComplete();
456 for (size_t i = 0; i < n; ++i) {
457 benchmark_singleton.get_weak_fast();
461 int main(int argc, char* argv[]) {
462 testing::InitGoogleTest(&argc, argv);
463 google::InitGoogleLogging(argv[0]);
464 google::ParseCommandLineFlags(&argc, &argv, true);
466 SingletonVault::singleton()->registrationComplete();
468 auto ret = RUN_ALL_TESTS();
470 folly::runBenchmarksOnFlag();