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.
17 #include <folly/experimental/Singleton.h>
23 SingletonVault::~SingletonVault() { destroyInstances(); }
25 void SingletonVault::destroyInstances() {
26 RWSpinLock::WriteHolder state_wh(&stateMutex_);
28 if (state_ == SingletonVaultState::Quiescing) {
31 state_ = SingletonVaultState::Quiescing;
33 RWSpinLock::ReadHolder state_rh(std::move(state_wh));
36 RWSpinLock::ReadHolder rh(&mutex_);
38 CHECK_GE(singletons_.size(), creation_order_.size());
40 for (auto type_iter = creation_order_.rbegin();
41 type_iter != creation_order_.rend();
43 destroyInstance(singletons_.find(*type_iter));
48 RWSpinLock::WriteHolder wh(&mutex_);
49 creation_order_.clear();
53 /* Destroy and clean-up one singleton. Must be invoked while holding
54 * a read lock on mutex_.
55 * @param typeDescriptor - the type key for the removed singleton.
57 void SingletonVault::destroyInstance(SingletonMap::iterator entry_it) {
58 const auto& type = entry_it->first;
59 auto& entry = *(entry_it->second);
60 if (entry.instance.use_count() > 1) {
61 LOG(ERROR) << "Singleton of type " << type.name() << " has a living "
62 << "reference at destroyInstances time; beware! Raw pointer "
63 << "is " << entry.instance.get() << " with use_count of "
64 << entry.instance.use_count();
66 entry.state = detail::SingletonEntryState::Dead;
67 entry.instance.reset();
70 void SingletonVault::reenableInstances() {
71 RWSpinLock::WriteHolder state_wh(&stateMutex_);
73 stateCheck(SingletonVaultState::Quiescing);
75 state_ = SingletonVaultState::Running;
78 SingletonVault* SingletonVault::singleton() {
79 static SingletonVault* vault = new SingletonVault();
83 void SingletonVault::scheduleDestroyInstances() {
84 class SingletonVaultDestructor {
86 ~SingletonVaultDestructor() {
87 SingletonVault::singleton()->destroyInstances();
91 // Here we intialize a singleton, which calls destroyInstances in its
92 // destructor. Because of singleton destruction order - it will be destroyed
93 // before all the singletons, which were initialized before it and after all
94 // the singletons initialized after it.
95 static SingletonVaultDestructor singletonVaultDestructor;