From: Andrii Grynenko Date: Tue, 14 Oct 2014 03:08:15 +0000 (-0700) Subject: Schedule destroyInstances only when first singleton is created X-Git-Tag: v0.22.0~274 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e5e3fde0cc5e35b87bec8714b0a7e6987a3d3975;p=folly.git 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 --- 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);