SingletonVault::~SingletonVault() { destroyInstances(); }
void SingletonVault::destroyInstances() {
+ RWSpinLock::WriteHolder state_wh(&stateMutex_);
+
+ if (state_ == SingletonVaultState::Quiescing) {
+ return;
+ }
+ state_ = SingletonVaultState::Quiescing;
+
+ RWSpinLock::ReadHolder state_rh(std::move(state_wh));
+
{
RWSpinLock::ReadHolder rh(&mutex_);
for (auto type_iter = creation_order_.rbegin();
type_iter != creation_order_.rend();
++type_iter) {
- auto type = *type_iter;
- auto it = singletons_.find(type);
- CHECK(it != singletons_.end());
- auto& entry = it->second;
- std::lock_guard<std::mutex> entry_guard(entry->mutex);
- if (entry->instance.use_count() > 1) {
- LOG(ERROR) << "Singleton of type " << type.name() << " has a living "
- << "reference at destroyInstances time; beware! Raw pointer "
- << "is " << entry->instance.get() << " with use_count of "
- << entry->instance.use_count();
- }
- entry->instance.reset();
- entry->state = SingletonEntryState::Dead;
- entry->state_condvar.notify_all();
+ destroyInstance(singletons_.find(*type_iter));
}
}
}
}
+/* Destroy and clean-up one singleton. Must be invoked while holding
+ * a read lock on mutex_.
+ * @param typeDescriptor - the type key for the removed singleton.
+ */
+void SingletonVault::destroyInstance(SingletonMap::iterator entry_it) {
+ const auto& type = entry_it->first;
+ auto& entry = *(entry_it->second);
+ if (entry.instance.use_count() > 1) {
+ LOG(ERROR) << "Singleton of type " << type.name() << " has a living "
+ << "reference at destroyInstances time; beware! Raw pointer "
+ << "is " << entry.instance.get() << " with use_count of "
+ << entry.instance.use_count();
+ }
+ entry.state = detail::SingletonEntryState::Dead;
+ entry.instance.reset();
+}
+
+void SingletonVault::reenableInstances() {
+ RWSpinLock::WriteHolder state_wh(&stateMutex_);
+
+ stateCheck(SingletonVaultState::Quiescing);
+
+ state_ = SingletonVaultState::Running;
+}
+
SingletonVault* SingletonVault::singleton() {
static SingletonVault* vault = new SingletonVault();
+ return vault;
+}
+void SingletonVault::scheduleDestroyInstances() {
class SingletonVaultDestructor {
public:
~SingletonVaultDestructor() {
SingletonVault::singleton()->destroyInstances();
}
};
- static SingletonVaultDestructor singletonVaultDestructor;
- return vault;
+ // Here we intialize a singleton, which calls destroyInstances in its
+ // destructor. Because of singleton destruction order - it will be destroyed
+ // before all the singletons, which were initialized before it and after all
+ // the singletons initialized after it.
+ static SingletonVaultDestructor singletonVaultDestructor;
}
}