From e5e3fde0cc5e35b87bec8714b0a7e6987a3d3975 Mon Sep 17 00:00:00 2001 From: Andrii Grynenko Date: Mon, 13 Oct 2014 20:08:15 -0700 Subject: [PATCH] Schedule destroyInstances only when first singleton is created Summary: Right now destroyInstances is scheduled when SingletonVault is requested. This may change singleton destruction order (folly::Singleton-managed vs unmanaged singletons) when new singleton is registered with folly::Singleton (no matter if it is even used). This diff changes it to be more stable. Test Plan: servicerouter unittests Reviewed By: chip@fb.com Subscribers: njormrod, mshneer FB internal diff: D1615213 Tasks: 5353022 --- folly/experimental/Singleton.cpp | 10 ++++++++-- folly/experimental/Singleton.h | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/folly/experimental/Singleton.cpp b/folly/experimental/Singleton.cpp index 27573fd2..5c1e650e 100644 --- a/folly/experimental/Singleton.cpp +++ b/folly/experimental/Singleton.cpp @@ -73,16 +73,22 @@ void SingletonVault::reenableInstances() { 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; } } diff --git a/folly/experimental/Singleton.h b/folly/experimental/Singleton.h index 99b633f0..eba1c57f 100644 --- a/folly/experimental/Singleton.h +++ b/folly/experimental/Singleton.h @@ -329,6 +329,16 @@ class SingletonVault { SingletonEntry(SingletonEntry&&) = delete; }; + // Initializes static object, which calls destroyInstances on destruction. + // Used to have better deletion ordering with singleton not managed by + // folly::Singleton. The desruction will happen in the following order: + // 1. Singletons, not managed by folly::Singleton, which were created after + // any of the singletons managed by folly::Singleton was requested. + // 2. All singletons managed by folly::Singleton + // 3. Singletons, not managed by folly::Singleton, which were created before + // any of the singletons managed by folly::Singleton was requested. + static void scheduleDestroyInstances(); + SingletonEntry* get_entry(detail::TypeDescriptor type) { RWSpinLock::ReadHolder rh(&mutex_); @@ -375,6 +385,13 @@ class SingletonVault { entry_lock.unlock(); // Can't use make_shared -- no support for a custom deleter, sadly. auto instance = std::shared_ptr(entry->create(), entry->teardown); + + // We should schedule destroyInstances() only after the singleton was + // created. This will ensure it will be destroyed before singletons, + // not managed by folly::Singleton, which were initialized in its + // constructor + scheduleDestroyInstances(); + entry_lock.lock(); CHECK(entry->state == SingletonEntryState::BeingBorn); -- 2.34.1