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.
17 #include <folly/Singleton.h>
25 constexpr std::chrono::seconds SingletonHolderBase::kDestroyWaitTime;
33 if (!leakedSingletons_.empty()) {
34 std::string leakedTypes;
35 for (const auto& singleton : leakedSingletons_) {
36 leakedTypes += "\t" + singleton.name() + "\n";
38 LOG(DFATAL) << "Singletons of the following types had living references "
39 << "after destroyInstances was finished:\n" << leakedTypes
40 << "beware! It is very likely that those singleton instances "
45 std::vector<detail::TypeDescriptor> leakedSingletons_;
49 // OS X doesn't support constructor priorities.
50 FatalHelper fatalHelper;
52 FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
57 SingletonVault::~SingletonVault() { destroyInstances(); }
59 void SingletonVault::destroyInstances() {
60 RWSpinLock::WriteHolder state_wh(&stateMutex_);
62 if (state_ == SingletonVaultState::Quiescing) {
65 state_ = SingletonVaultState::Quiescing;
67 RWSpinLock::ReadHolder state_rh(std::move(state_wh));
70 RWSpinLock::ReadHolder rh(&mutex_);
72 CHECK_GE(singletons_.size(), creation_order_.size());
74 for (auto type_iter = creation_order_.rbegin();
75 type_iter != creation_order_.rend();
77 singletons_[*type_iter]->destroyInstance();
80 for (auto& singleton_type: creation_order_) {
81 auto singleton = singletons_[singleton_type];
82 if (!singleton->hasLiveInstance()) {
86 fatalHelper.leakedSingletons_.push_back(singleton->type());
91 RWSpinLock::WriteHolder wh(&mutex_);
92 creation_order_.clear();
96 void SingletonVault::reenableInstances() {
97 RWSpinLock::WriteHolder state_wh(&stateMutex_);
99 stateCheck(SingletonVaultState::Quiescing);
101 state_ = SingletonVaultState::Running;
104 void SingletonVault::scheduleDestroyInstances() {
105 RequestContext::saveContext();
107 class SingletonVaultDestructor {
109 ~SingletonVaultDestructor() {
110 SingletonVault::singleton()->destroyInstances();
114 // Here we intialize a singleton, which calls destroyInstances in its
115 // destructor. Because of singleton destruction order - it will be destroyed
116 // before all the singletons, which were initialized before it and after all
117 // the singletons initialized after it.
118 static SingletonVaultDestructor singletonVaultDestructor;