Remove unused variables
[folly.git] / folly / experimental / Singleton.h
index c861e1bc18cdb11110c401facf1bcf9ff74660df..7af17256337cafed16e53bbc31c61e645ee6ef7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 // circular dependency, a runtime error will occur.
 //
 // You can have multiple singletons of the same underlying type, but
-// each must be given a unique name:
+// each must be given a unique tag. If no tag is specified - default tag is used
 //
 // namespace {
-// folly::Singleton<MyExpensiveService> s1("name1");
-// folly::Singleton<MyExpensiveService> s2("name2");
+// struct Tag1 {};
+// struct Tag2 {};
+// folly::Singleton<MyExpensiveService> s_default();
+// folly::Singleton<MyExpensiveService, Tag1> s1();
+// folly::Singleton<MyExpensiveService, Tag2> s2();
 // }
 // ...
-// MyExpensiveService* svc1 = Singleton<MyExpensiveService>::get("name1");
-// MyExpensiveService* svc2 = Singleton<MyExpensiveService>::get("name2");
+// MyExpensiveService* svc_default = s_default.get();
+// MyExpensiveService* svc1 = s1.get();
+// MyExpensiveService* svc2 = s2.get();
 //
 // By default, the singleton instance is constructed via new and
 // deleted via delete, but this is configurable:
 // TeardownFunc for each singleton, in the reverse order they were
 // created.  It is your responsibility to ensure your singletons can
 // handle cases where the singletons they depend on go away, however.
+// Singletons won't be recreated after destroyInstances call. If you
+// want to re-enable singleton creation (say after fork was called) you
+// should call reenableInstances.
 
 #pragma once
+#include <folly/Baton.h>
 #include <folly/Exception.h>
 #include <folly/Hash.h>
+#include <folly/Memory.h>
+#include <folly/RWSpinLock.h>
+#include <folly/Demangle.h>
+#include <folly/io/async/Request.h>
 
+#include <algorithm>
 #include <vector>
 #include <mutex>
 #include <thread>
@@ -114,124 +127,224 @@ namespace folly {
 // ensure registrationComplete() is called near the top of your main()
 // function, otherwise no singletons can be instantiated.
 
+class SingletonVault;
+
 namespace detail {
 
-const char* const kDefaultTypeDescriptorName = "(default)";
+struct DefaultTag {};
+
 // A TypeDescriptor is the unique handle for a given singleton.  It is
 // a combinaiton of the type and of the optional name, and is used as
 // a key in unordered_maps.
 class TypeDescriptor {
  public:
-  TypeDescriptor(const std::type_info& ti, std::string name)
-      : ti_(ti), name_(name) {
-    if (name_ == kDefaultTypeDescriptorName) {
-      LOG(DFATAL) << "Caller used the default name as their literal name; "
-                  << "name your singleton something other than "
-                  << kDefaultTypeDescriptorName;
+  TypeDescriptor(const std::type_info& ti,
+                 const std::type_info& tag_ti)
+      : ti_(ti), tag_ti_(tag_ti) {
+  }
+
+  TypeDescriptor(const TypeDescriptor& other)
+      : ti_(other.ti_), tag_ti_(other.tag_ti_) {
+  }
+
+  TypeDescriptor& operator=(const TypeDescriptor& other) {
+    if (this != &other) {
+      ti_ = other.ti_;
+      tag_ti_ = other.tag_ti_;
     }
+
+    return *this;
   }
 
   std::string name() const {
-    std::string ret = ti_.name();
-    ret += "/";
-    if (name_.empty()) {
-      ret += kDefaultTypeDescriptorName;
-    } else {
-      ret += name_;
+    auto ret = demangle(ti_.name());
+    if (tag_ti_ != std::type_index(typeid(DefaultTag))) {
+      ret += "/";
+      ret += demangle(tag_ti_.name());
     }
-    return ret;
+    return ret.toStdString();
   }
 
   friend class TypeDescriptorHasher;
 
   bool operator==(const TypeDescriptor& other) const {
-    return ti_ == other.ti_ && name_ == other.name_;
+    return ti_ == other.ti_ && tag_ti_ == other.tag_ti_;
   }
 
  private:
-  const std::type_index ti_;
-  const std::string name_;
+  std::type_index ti_;
+  std::type_index tag_ti_;
 };
 
 class TypeDescriptorHasher {
  public:
   size_t operator()(const TypeDescriptor& ti) const {
-    return folly::hash::hash_combine(ti.ti_, ti.name_);
+    return folly::hash::hash_combine(ti.ti_, ti.tag_ti_);
   }
 };
+
+// This interface is used by SingletonVault to interact with SingletonHolders.
+// Having a non-template interface allows SingletonVault to keep a list of all
+// SingletonHolders.
+class SingletonHolderBase {
+ public:
+  virtual ~SingletonHolderBase() {}
+
+  virtual TypeDescriptor type() = 0;
+  virtual bool hasLiveInstance() = 0;
+  virtual void destroyInstance() = 0;
+
+ protected:
+  static constexpr std::chrono::seconds kDestroyWaitTime{5};
+};
+
+// An actual instance of a singleton, tracking the instance itself,
+// its state as described above, and the create and teardown
+// functions.
+template <typename T>
+struct SingletonHolder : public SingletonHolderBase {
+ public:
+  typedef std::function<void(T*)> TeardownFunc;
+  typedef std::function<T*(void)> CreateFunc;
+
+  template <typename Tag, typename VaultTag>
+  inline static SingletonHolder<T>& singleton();
+
+  inline T* get();
+  inline std::weak_ptr<T> get_weak();
+
+  void registerSingleton(CreateFunc c, TeardownFunc t);
+  void registerSingletonMock(CreateFunc c, TeardownFunc t);
+  virtual TypeDescriptor type();
+  virtual bool hasLiveInstance();
+  virtual void destroyInstance();
+
+ private:
+  SingletonHolder(TypeDescriptor type, SingletonVault& vault);
+
+  void createInstance();
+
+  enum class SingletonHolderState {
+    NotRegistered,
+    Dead,
+    Living,
+  };
+
+  TypeDescriptor type_;
+  SingletonVault& vault_;
+
+  // mutex protects the entire entry during construction/destruction
+  std::mutex mutex_;
+
+  // State of the singleton entry. If state is Living, instance_ptr and
+  // instance_weak can be safely accessed w/o synchronization.
+  std::atomic<SingletonHolderState> state_{SingletonHolderState::NotRegistered};
+
+  // the thread creating the singleton (only valid while creating an object)
+  std::thread::id creating_thread_;
+
+  // The singleton itself and related functions.
+
+  // holds a shared_ptr to singleton instance, set when state is changed from
+  // Dead to Living. Reset when state is changed from Living to Dead.
+  std::shared_ptr<T> instance_;
+  // weak_ptr to the singleton instance, set when state is changed from Dead
+  // to Living. We never write to this object after initialization, so it is
+  // safe to read it from different threads w/o synchronization if we know
+  // that state is set to Living
+  std::weak_ptr<T> instance_weak_;
+  // Time we wait on destroy_baton after releasing Singleton shared_ptr.
+  std::shared_ptr<folly::Baton<>> destroy_baton_;
+  T* instance_ptr_ = nullptr;
+  CreateFunc create_ = nullptr;
+  TeardownFunc teardown_ = nullptr;
+
+  std::shared_ptr<std::atomic<bool>> print_destructor_stack_trace_;
+
+  SingletonHolder(const SingletonHolder&) = delete;
+  SingletonHolder& operator=(const SingletonHolder&) = delete;
+  SingletonHolder& operator=(SingletonHolder&&) = delete;
+  SingletonHolder(SingletonHolder&&) = delete;
+};
+
 }
 
 class SingletonVault {
  public:
-  SingletonVault() {};
+  enum class Type { Strict, Relaxed };
+
+  explicit SingletonVault(Type type = Type::Relaxed) : type_(type) {}
+
+  // Destructor is only called by unit tests to check destroyInstances.
   ~SingletonVault();
 
   typedef std::function<void(void*)> TeardownFunc;
   typedef std::function<void*(void)> CreateFunc;
 
-  // Register a singleton of a given type with the create and teardown
+  // Ensure that Singleton has not been registered previously and that
+  // registration is not complete. If validations succeeds,
+  // register a singleton of a given type with the create and teardown
   // functions.
-  void registerSingleton(detail::TypeDescriptor type,
-                         CreateFunc create,
-                         TeardownFunc teardown) {
-    std::lock_guard<std::mutex> guard(mutex_);
-
-    CHECK_THROW(state_ == SingletonVaultState::Registering, std::logic_error);
-    CHECK_THROW(singletons_.find(type) == singletons_.end(), std::logic_error);
-    auto& entry = singletons_[type];
-    if (!entry) {
-      entry.reset(new SingletonEntry);
+  void registerSingleton(detail::SingletonHolderBase* entry) {
+    RWSpinLock::ReadHolder rh(&stateMutex_);
+
+    stateCheck(SingletonVaultState::Running);
+
+    if (UNLIKELY(registrationComplete_)) {
+      throw std::logic_error(
+        "Registering singleton after registrationComplete().");
     }
 
-    std::lock_guard<std::mutex> entry_guard(entry->mutex);
-    CHECK(entry->instance == nullptr);
-    CHECK(create);
-    CHECK(teardown);
-    entry->create = create;
-    entry->teardown = teardown;
-    entry->state = SingletonEntryState::Dead;
+    RWSpinLock::ReadHolder rhMutex(&mutex_);
+    CHECK_THROW(singletons_.find(entry->type()) == singletons_.end(),
+                std::logic_error);
+
+    RWSpinLock::UpgradedHolder wh(&mutex_);
+    singletons_[entry->type()] = entry;
   }
 
   // Mark registration is complete; no more singletons can be
   // registered at this point.
   void registrationComplete() {
-    std::lock_guard<std::mutex> guard(mutex_);
-    CHECK_THROW(state_ == SingletonVaultState::Registering, std::logic_error);
-    state_ = SingletonVaultState::Running;
-  }
+    RequestContext::getStaticContext();
+    std::atexit([](){ SingletonVault::singleton()->destroyInstances(); });
 
-  // Destroy all singletons; when complete, the vault can create
-  // singletons once again, or remain dormant.
-  void destroyInstances();
+    RWSpinLock::WriteHolder wh(&stateMutex_);
 
-  // Retrieve a singleton from the vault, creating it if necessary.
-  std::shared_ptr<void> get_shared(detail::TypeDescriptor type) {
-    std::unique_lock<std::mutex> lock(mutex_);
-    auto entry = get_entry(type, &lock);
-    return entry->instance;
-  }
+    stateCheck(SingletonVaultState::Running);
+
+    if (type_ == Type::Strict) {
+      for (const auto& p: singletons_) {
+        if (p.second->hasLiveInstance()) {
+          throw std::runtime_error(
+            "Singleton created before registration was complete.");
+        }
+      }
+    }
 
-  // This function is inherently racy since we don't hold the
-  // shared_ptr that contains the Singleton.  It is the caller's
-  // responsibility to be sane with this, but it is preferable to use
-  // the weak_ptr interface for true safety.
-  void* get_ptr(detail::TypeDescriptor type) {
-    std::unique_lock<std::mutex> lock(mutex_);
-    auto entry = get_entry(type, &lock);
-    return entry->instance_ptr;
+    registrationComplete_ = true;
   }
 
+  // Destroy all singletons; when complete, the vault can't create
+  // singletons once again until reenableInstances() is called.
+  void destroyInstances();
+
+  // Enable re-creating singletons after destroyInstances() was called.
+  void reenableInstances();
+
   // For testing; how many registered and living singletons we have.
   size_t registeredSingletonCount() const {
-    std::lock_guard<std::mutex> guard(mutex_);
+    RWSpinLock::ReadHolder rh(&mutex_);
+
     return singletons_.size();
   }
 
   size_t livingSingletonCount() const {
-    std::lock_guard<std::mutex> guard(mutex_);
+    RWSpinLock::ReadHolder rh(&mutex_);
+
     size_t ret = 0;
     for (const auto& p : singletons_) {
-      if (p.second->instance) {
+      if (p.second->hasLiveInstance()) {
         ++ret;
       }
     }
@@ -241,122 +354,69 @@ class SingletonVault {
 
   // A well-known vault; you can actually have others, but this is the
   // default.
-  static SingletonVault* singleton();
+  static SingletonVault* singleton() {
+    return singleton<>();
+  }
+
+  // Gets singleton vault for any Tag. Non-default tag should be used in unit
+  // tests only.
+  template <typename VaultTag = detail::DefaultTag>
+  static SingletonVault* singleton() {
+    static SingletonVault* vault = new SingletonVault();
+    return vault;
+  }
+
+  typedef std::string(*StackTraceGetterPtr)();
+
+  static std::atomic<StackTraceGetterPtr>& stackTraceGetter() {
+    static std::atomic<StackTraceGetterPtr> stackTraceGetterPtr;
+    return stackTraceGetterPtr;
+  }
 
  private:
+  template <typename T>
+  friend class detail::SingletonHolder;
+
   // The two stages of life for a vault, as mentioned in the class comment.
   enum class SingletonVaultState {
-    Registering,
     Running,
+    Quiescing,
   };
 
-  // Each singleton in the vault can be in three states: dead
-  // (registered but never created), being born (running the
-  // CreateFunc), and living (CreateFunc returned an instance).
-  enum class SingletonEntryState {
-    Dead,
-    BeingBorn,
-    Living,
-  };
-
-  // An actual instance of a singleton, tracking the instance itself,
-  // its state as described above, and the create and teardown
-  // functions.
-  struct SingletonEntry {
-    // mutex protects the entire entry
-    std::mutex mutex;
-
-    // state changes notify state_condvar
-    SingletonEntryState state = SingletonEntryState::Dead;
-    std::condition_variable state_condvar;
-
-    // the thread creating the singleton
-    std::thread::id creating_thread;
-
-    // The singleton itself and related functions.
-    std::shared_ptr<void> instance;
-    void* instance_ptr = nullptr;
-    CreateFunc create = nullptr;
-    TeardownFunc teardown = nullptr;
-
-    SingletonEntry() = default;
-    SingletonEntry(const SingletonEntry&) = delete;
-    SingletonEntry& operator=(const SingletonEntry&) = delete;
-    SingletonEntry& operator=(SingletonEntry&&) = delete;
-    SingletonEntry(SingletonEntry&&) = delete;
-  };
+  // Each singleton in the vault can be in two states: dead
+  // (registered but never created), living (CreateFunc returned an instance).
 
-  // Get a pointer to the living SingletonEntry for the specified
-  // type.  The singleton is created as part of this function, if
-  // necessary.
-  SingletonEntry* get_entry(detail::TypeDescriptor type,
-                            std::unique_lock<std::mutex>* lock) {
-    // mutex must be held when calling this function
-    if (state_ != SingletonVaultState::Running) {
-      throw std::logic_error(
-          "Attempt to load a singleton before "
-          "SingletonVault::registrationComplete was called (hint: you probably "
-          "didn't call initFacebook)");
+  void stateCheck(SingletonVaultState expected,
+                  const char* msg="Unexpected singleton state change") {
+    if (expected != state_) {
+        throw std::logic_error(msg);
     }
-
-    auto it = singletons_.find(type);
-    if (it == singletons_.end()) {
-      throw std::out_of_range(std::string("non-existent singleton: ") +
-                              type.name());
-    }
-
-    auto entry = it->second.get();
-    std::unique_lock<std::mutex> entry_lock(entry->mutex);
-
-    if (entry->state == SingletonEntryState::BeingBorn) {
-      // If this thread is trying to give birth to the singleton, it's
-      // a circular dependency and we must panic.
-      if (entry->creating_thread == std::this_thread::get_id()) {
-        throw std::out_of_range(std::string("circular singleton dependency: ") +
-                                type.name());
-      }
-
-      // Otherwise, another thread is constructing the singleton;
-      // let's wait on a condvar to see it complete.  We release and
-      // reaquire lock while waiting on the entry to resolve its state.
-      lock->unlock();
-      entry->state_condvar.wait(entry_lock, [&entry]() {
-        return entry->state != SingletonEntryState::BeingBorn;
-      });
-      lock->lock();
-    }
-
-    if (entry->instance == nullptr) {
-      CHECK(entry->state == SingletonEntryState::Dead);
-      entry->state = SingletonEntryState::BeingBorn;
-      entry->creating_thread = std::this_thread::get_id();
-
-      entry_lock.unlock();
-      lock->unlock();
-      // Can't use make_shared -- no support for a custom deleter, sadly.
-      auto instance = std::shared_ptr<void>(entry->create(), entry->teardown);
-      lock->lock();
-      entry_lock.lock();
-
-      CHECK(entry->state == SingletonEntryState::BeingBorn);
-      entry->instance = instance;
-      entry->instance_ptr = instance.get();
-      entry->state = SingletonEntryState::Living;
-      entry->state_condvar.notify_all();
-
-      creation_order_.push_back(type);
-    }
-    CHECK(entry->state == SingletonEntryState::Living);
-    return entry;
   }
 
-  mutable std::mutex mutex_;
-  typedef std::unique_ptr<SingletonEntry> SingletonEntryPtr;
-  std::unordered_map<detail::TypeDescriptor,
-                     SingletonEntryPtr,
-                     detail::TypeDescriptorHasher> singletons_;
+  // This method only matters if registrationComplete() is never called.
+  // Otherwise destroyInstances is scheduled to be executed atexit.
+  //
+  // 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();
+
+  typedef std::unordered_map<detail::TypeDescriptor,
+                             detail::SingletonHolderBase*,
+                             detail::TypeDescriptorHasher> SingletonMap;
+
+  mutable folly::RWSpinLock mutex_;
+  SingletonMap singletons_;
   std::vector<detail::TypeDescriptor> creation_order_;
-  SingletonVaultState state_ = SingletonVaultState::Registering;
+  SingletonVaultState state_{SingletonVaultState::Running};
+  bool registrationComplete_{false};
+  folly::RWSpinLock stateMutex_;
+  Type type_{Type::Relaxed};
 };
 
 // This is the wrapper class that most users actually interact with.
@@ -364,7 +424,9 @@ class SingletonVault {
 // singletons.  Create instances of this class in the global scope of
 // type Singleton<T> to register your singleton for later access via
 // Singleton<T>::get().
-template <typename T>
+template <typename T,
+          typename Tag = detail::DefaultTag,
+          typename VaultTag = detail::DefaultTag /* for testing */>
 class Singleton {
  public:
   typedef std::function<T*(void)> CreateFunc;
@@ -373,97 +435,83 @@ class Singleton {
   // Generally your program life cycle should be fine with calling
   // get() repeatedly rather than saving the reference, and then not
   // call get() during process shutdown.
-  static T* get(SingletonVault* vault = nullptr /* for testing */) {
-    return get_ptr({typeid(T), ""}, vault);
-  }
-
-  static T* get(const char* name,
-                SingletonVault* vault = nullptr /* for testing */) {
-    return get_ptr({typeid(T), name}, vault);
+  static T* get() {
+    return getEntry().get();
   }
 
   // If, however, you do need to hold a reference to the specific
   // singleton, you can try to do so with a weak_ptr.  Avoid this when
   // possible but the inability to lock the weak pointer can be a
   // signal that the vault has been destroyed.
-  static std::weak_ptr<T> get_weak(
-      SingletonVault* vault = nullptr /* for testing */) {
-    return get_weak("", vault);
+  static std::weak_ptr<T> get_weak() {
+    return getEntry().get_weak();
   }
 
-  static std::weak_ptr<T> get_weak(
-      const char* name, SingletonVault* vault = nullptr /* for testing */) {
-    return std::weak_ptr<T>(get_shared({typeid(T), name}, vault));
-  }
+  // Allow the Singleton<t> instance to also retrieve the underlying
+  // singleton, if desired.
+  T& operator*() { return *get(); }
+  T* operator->() { return get(); }
 
-  std::weak_ptr<T> get_weak(const char* name) {
-    return std::weak_ptr<T>(get_shared({typeid(T), name}, vault_));
+  explicit Singleton(std::nullptr_t _ = nullptr,
+                     Singleton::TeardownFunc t = nullptr) :
+      Singleton ([]() { return new T; }, std::move(t)) {
   }
 
-  // Allow the Singleton<t> instance to also retrieve the underlying
-  // singleton, if desired.
-  T* ptr() { return get_ptr(type_descriptor_, vault_); }
-  T& operator*() { return *ptr(); }
-  T* operator->() { return ptr(); }
+  explicit Singleton(Singleton::CreateFunc c,
+                     Singleton::TeardownFunc t = nullptr) {
+    if (c == nullptr) {
+      throw std::logic_error(
+        "nullptr_t should be passed if you want T to be default constructed");
+    }
 
-  explicit Singleton(Singleton::CreateFunc c = nullptr,
-                     Singleton::TeardownFunc t = nullptr,
-                     SingletonVault* vault = nullptr /* for testing */)
-      : Singleton({typeid(T), ""}, c, t, vault) {}
+    auto vault = SingletonVault::singleton<VaultTag>();
+    getEntry().registerSingleton(std::move(c), getTeardownFunc(std::move(t)));
+    vault->registerSingleton(&getEntry());
+  }
 
-  explicit Singleton(const char* name,
-                     Singleton::CreateFunc c = nullptr,
-                     Singleton::TeardownFunc t = nullptr,
-                     SingletonVault* vault = nullptr /* for testing */)
-      : Singleton({typeid(T), name}, c, t, vault) {}
+  /**
+  * Construct and inject a mock singleton which should be used only from tests.
+  * Unlike regular singletons which are initialized once per process lifetime,
+  * mock singletons live for the duration of a test. This means that one process
+  * running multiple tests can initialize and register the same singleton
+  * multiple times. This functionality should be used only from tests
+  * since it relaxes validation and performance in order to be able to perform
+  * the injection. The returned mock singleton is functionality identical to
+  * regular singletons.
+  */
+  static void make_mock(std::nullptr_t c = nullptr,
+                        typename Singleton<T>::TeardownFunc t = nullptr) {
+    make_mock([]() { return new T; }, t);
+  }
 
- private:
-  explicit Singleton(detail::TypeDescriptor type,
-                     Singleton::CreateFunc c = nullptr,
-                     Singleton::TeardownFunc t = nullptr,
-                     SingletonVault* vault = nullptr /* for testing */)
-      : type_descriptor_(type) {
+  static void make_mock(CreateFunc c,
+                        typename Singleton<T>::TeardownFunc t = nullptr) {
     if (c == nullptr) {
-      c = []() { return new T; };
-    }
-    SingletonVault::TeardownFunc teardown;
-    if (t == nullptr) {
-      teardown = [](void* v) { delete static_cast<T*>(v); };
-    } else {
-      teardown = [t](void* v) { t(static_cast<T*>(v)); };
+      throw std::logic_error(
+        "nullptr_t should be passed if you want T to be default constructed");
     }
 
-    if (vault == nullptr) {
-      vault = SingletonVault::singleton();
-    }
-    vault_ = vault;
-    vault->registerSingleton(type, c, teardown);
-  }
+    auto& entry = getEntry();
 
-  static T* get_ptr(detail::TypeDescriptor type_descriptor = {typeid(T), ""},
-                    SingletonVault* vault = nullptr /* for testing */) {
-    return static_cast<T*>(
-        (vault ?: SingletonVault::singleton())->get_ptr(type_descriptor));
+    entry.registerSingletonMock(c, getTeardownFunc(t));
   }
 
-  // Don't use this function, it's private for a reason!  Using it
-  // would defeat the *entire purpose* of the vault in that we lose
-  // the ability to guarantee that, after a destroyInstances is
-  // called, all instances are, in fact, destroyed.  You should use
-  // weak_ptr if you need to hold a reference to the singleton and
-  // guarantee briefly that it exists.
-  //
-  // Yes, you can just get the weak pointer and lock it, but hopefully
-  // if you have taken the time to read this far, you see why that
-  // would be bad.
-  static std::shared_ptr<T> get_shared(
-      detail::TypeDescriptor type_descriptor = {typeid(T), ""},
-      SingletonVault* vault = nullptr /* for testing */) {
-    return std::static_pointer_cast<T>(
-        (vault ?: SingletonVault::singleton())->get_shared(type_descriptor));
+ private:
+  inline static detail::SingletonHolder<T>& getEntry() {
+    return detail::SingletonHolder<T>::template singleton<Tag, VaultTag>();
   }
 
-  detail::TypeDescriptor type_descriptor_;
-  SingletonVault* vault_;
+  // Construct TeardownFunc.
+  static typename detail::SingletonHolder<T>::TeardownFunc getTeardownFunc(
+      TeardownFunc t)  {
+    if (t == nullptr) {
+      return  [](T* v) { delete v; };
+    } else {
+      return t;
+    }
+  }
 };
+
 }
+
+#include <folly/experimental/Singleton-inl.h>