get_fast/get_weak_fast API for folly::Singleton
[folly.git] / folly / experimental / Singleton.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 // SingletonVault - a library to manage the creation and destruction
18 // of interdependent singletons.
19 //
20 // Basic usage of this class is very simple; suppose you have a class
21 // called MyExpensiveService, and you only want to construct one (ie,
22 // it's a singleton), but you only want to construct it if it is used.
23 //
24 // In your .h file:
25 // class MyExpensiveService { ... };
26 //
27 // In your .cpp file:
28 // namespace { folly::Singleton<MyExpensiveService> the_singleton; }
29 //
30 // Code can access it via:
31 //
32 // MyExpensiveService* instance = Singleton<MyExpensiveService>::get();
33 // or
34 // std::weak_ptr<MyExpensiveService> instance =
35 //     Singleton<MyExpensiveService>::get_weak();
36 //
37 // You also can directly access it by the variable defining the
38 // singleton rather than via get(), and even treat that variable like
39 // a smart pointer (dereferencing it or using the -> operator).
40 //
41 // Please note, however, that all non-weak_ptr interfaces are
42 // inherently subject to races with destruction.  Use responsibly.
43 //
44 // The singleton will be created on demand.  If the constructor for
45 // MyExpensiveService actually makes use of *another* Singleton, then
46 // the right thing will happen -- that other singleton will complete
47 // construction before get() returns.  However, in the event of a
48 // circular dependency, a runtime error will occur.
49 //
50 // You can have multiple singletons of the same underlying type, but
51 // each must be given a unique name:
52 //
53 // namespace {
54 // folly::Singleton<MyExpensiveService> s1("name1");
55 // folly::Singleton<MyExpensiveService> s2("name2");
56 // }
57 // ...
58 // MyExpensiveService* svc1 = Singleton<MyExpensiveService>::get("name1");
59 // MyExpensiveService* svc2 = Singleton<MyExpensiveService>::get("name2");
60 //
61 // By default, the singleton instance is constructed via new and
62 // deleted via delete, but this is configurable:
63 //
64 // namespace { folly::Singleton<MyExpensiveService> the_singleton(create,
65 //                                                                destroy); }
66 //
67 // Where create and destroy are functions, Singleton<T>::CreateFunc
68 // Singleton<T>::TeardownFunc.
69 //
70 // What if you need to destroy all of your singletons?  Say, some of
71 // your singletons manage threads, but you need to fork?  Or your unit
72 // test wants to clean up all global state?  Then you can call
73 // SingletonVault::singleton()->destroyInstances(), which invokes the
74 // TeardownFunc for each singleton, in the reverse order they were
75 // created.  It is your responsibility to ensure your singletons can
76 // handle cases where the singletons they depend on go away, however.
77 // Singletons won't be recreated after destroyInstances call. If you
78 // want to re-enable singleton creation (say after fork was called) you
79 // should call reenableInstances.
80
81 #pragma once
82 #include <folly/Exception.h>
83 #include <folly/Hash.h>
84 #include <folly/Memory.h>
85 #include <folly/RWSpinLock.h>
86
87 #include <algorithm>
88 #include <vector>
89 #include <mutex>
90 #include <thread>
91 #include <condition_variable>
92 #include <string>
93 #include <unordered_map>
94 #include <functional>
95 #include <typeinfo>
96 #include <typeindex>
97
98 #include <glog/logging.h>
99
100 namespace folly {
101
102 // For actual usage, please see the Singleton<T> class at the bottom
103 // of this file; that is what you will actually interact with.
104
105 // SingletonVault is the class that manages singleton instances.  It
106 // is unaware of the underlying types of singletons, and simply
107 // manages lifecycles and invokes CreateFunc and TeardownFunc when
108 // appropriate.  In general, you won't need to interact with the
109 // SingletonVault itself.
110 //
111 // A vault goes through a few stages of life:
112 //
113 //   1. Registration phase; singletons can be registered, but no
114 //      singleton can be created.
115 //   2. registrationComplete() has been called; singletons can no
116 //      longer be registered, but they can be created.
117 //   3. A vault can return to stage 1 when destroyInstances is called.
118 //
119 // In general, you don't need to worry about any of the above; just
120 // ensure registrationComplete() is called near the top of your main()
121 // function, otherwise no singletons can be instantiated.
122
123 namespace detail {
124
125 const char* const kDefaultTypeDescriptorName = "(default)";
126 // A TypeDescriptor is the unique handle for a given singleton.  It is
127 // a combinaiton of the type and of the optional name, and is used as
128 // a key in unordered_maps.
129 class TypeDescriptor {
130  public:
131   TypeDescriptor(const std::type_info& ti, std::string name__)
132       : ti_(ti), name_(name__) {
133     if (name_ == kDefaultTypeDescriptorName) {
134       LOG(DFATAL) << "Caller used the default name as their literal name; "
135                   << "name your singleton something other than "
136                   << kDefaultTypeDescriptorName;
137     }
138   }
139
140   TypeDescriptor(const TypeDescriptor& other)
141       : ti_(other.ti_), name_(other.name_) {
142   }
143
144   TypeDescriptor& operator=(const TypeDescriptor& other) {
145     if (this != &other) {
146       name_ = other.name_;
147       ti_ = other.ti_;
148     }
149
150     return *this;
151   }
152
153   std::string name() const {
154     std::string ret = ti_.name();
155     ret += "/";
156     if (name_.empty()) {
157       ret += kDefaultTypeDescriptorName;
158     } else {
159       ret += name_;
160     }
161     return ret;
162   }
163
164   std::string name_raw() const {
165     return name_;
166   }
167
168   friend class TypeDescriptorHasher;
169
170   bool operator==(const TypeDescriptor& other) const {
171     return ti_ == other.ti_ && name_ == other.name_;
172   }
173
174  private:
175   std::type_index ti_;
176   std::string name_;
177 };
178
179 class TypeDescriptorHasher {
180  public:
181   size_t operator()(const TypeDescriptor& ti) const {
182     return folly::hash::hash_combine(ti.ti_, ti.name_);
183   }
184 };
185
186 enum class SingletonEntryState {
187   Dead,
188   Living,
189 };
190
191 // An actual instance of a singleton, tracking the instance itself,
192 // its state as described above, and the create and teardown
193 // functions.
194 struct SingletonEntry {
195   typedef std::function<void(void*)> TeardownFunc;
196   typedef std::function<void*(void)> CreateFunc;
197
198   SingletonEntry(CreateFunc c, TeardownFunc t) :
199       create(std::move(c)), teardown(std::move(t)) {}
200
201   // mutex protects the entire entry during construction/destruction
202   std::mutex mutex;
203
204   // State of the singleton entry. If state is Living, instance_ptr and
205   // instance_weak can be safely accessed w/o synchronization.
206   std::atomic<SingletonEntryState> state{SingletonEntryState::Dead};
207
208   // the thread creating the singleton (only valid while creating an object)
209   std::thread::id creating_thread;
210
211   // The singleton itself and related functions.
212
213   // holds a shared_ptr to singleton instance, set when state is changed from
214   // Dead to Living. Reset when state is changed from Living to Dead.
215   std::shared_ptr<void> instance;
216   // weak_ptr to the singleton instance, set when state is changed from Dead
217   // to Living. We never write to this object after initialization, so it is
218   // safe to read it from different threads w/o synchronization if we know
219   // that state is set to Living
220   std::weak_ptr<void> instance_weak;
221   void* instance_ptr = nullptr;
222   CreateFunc create = nullptr;
223   TeardownFunc teardown = nullptr;
224
225   SingletonEntry(const SingletonEntry&) = delete;
226   SingletonEntry& operator=(const SingletonEntry&) = delete;
227   SingletonEntry& operator=(SingletonEntry&&) = delete;
228   SingletonEntry(SingletonEntry&&) = delete;
229 };
230
231 }
232
233 class SingletonVault {
234  public:
235   enum class Type { Strict, Relaxed };
236
237   explicit SingletonVault(Type type = Type::Relaxed) : type_(type) {}
238
239   // Destructor is only called by unit tests to check destroyInstances.
240   ~SingletonVault();
241
242   typedef std::function<void(void*)> TeardownFunc;
243   typedef std::function<void*(void)> CreateFunc;
244
245   // Ensure that Singleton has not been registered previously and that
246   // registration is not complete. If validations succeeds,
247   // register a singleton of a given type with the create and teardown
248   // functions.
249   detail::SingletonEntry& registerSingleton(detail::TypeDescriptor type,
250                                             CreateFunc create,
251                                             TeardownFunc teardown) {
252     RWSpinLock::ReadHolder rh(&stateMutex_);
253
254     stateCheck(SingletonVaultState::Running);
255
256     if (UNLIKELY(registrationComplete_)) {
257       throw std::logic_error(
258         "Registering singleton after registrationComplete().");
259     }
260
261     RWSpinLock::ReadHolder rhMutex(&mutex_);
262     CHECK_THROW(singletons_.find(type) == singletons_.end(), std::logic_error);
263
264     return registerSingletonImpl(type, create, teardown);
265   }
266
267   // Register a singleton of a given type with the create and teardown
268   // functions. Must hold reader locks on stateMutex_ and mutex_
269   // when invoking this function.
270   detail::SingletonEntry& registerSingletonImpl(detail::TypeDescriptor type,
271                              CreateFunc create,
272                              TeardownFunc teardown) {
273     RWSpinLock::UpgradedHolder wh(&mutex_);
274
275     singletons_[type] =
276       folly::make_unique<detail::SingletonEntry>(std::move(create),
277                                                  std::move(teardown));
278     return *singletons_[type];
279   }
280
281   /* Register a mock singleton used for testing of singletons which
282    * depend on other private singletons which cannot be otherwise injected.
283    */
284   void registerMockSingleton(detail::TypeDescriptor type,
285                              CreateFunc create,
286                              TeardownFunc teardown) {
287     RWSpinLock::ReadHolder rh(&stateMutex_);
288     RWSpinLock::ReadHolder rhMutex(&mutex_);
289
290     auto entry_it = singletons_.find(type);
291     // Mock singleton registration, we allow existing entry to be overridden.
292     if (entry_it == singletons_.end()) {
293       throw std::logic_error(
294         "Registering mock before the singleton was registered");
295     }
296
297     {
298       auto& entry = *(entry_it->second);
299       // Destroy existing singleton.
300       std::lock_guard<std::mutex> entry_lg(entry.mutex);
301
302       destroyInstance(entry_it);
303       entry.create = create;
304       entry.teardown = teardown;
305     }
306
307     // Upgrade to write lock.
308     RWSpinLock::UpgradedHolder whMutex(&mutex_);
309
310     // Remove singleton from creation order and singletons_.
311     // This happens only in test code and not frequently.
312     // Performance is not a concern here.
313     auto creation_order_it = std::find(
314       creation_order_.begin(),
315       creation_order_.end(),
316       type);
317     if (creation_order_it != creation_order_.end()) {
318       creation_order_.erase(creation_order_it);
319     }
320   }
321
322   // Mark registration is complete; no more singletons can be
323   // registered at this point.
324   void registrationComplete() {
325     std::atexit([](){ SingletonVault::singleton()->destroyInstances(); });
326
327     RWSpinLock::WriteHolder wh(&stateMutex_);
328
329     stateCheck(SingletonVaultState::Running);
330
331     if (type_ == Type::Strict) {
332       for (const auto& id_singleton_entry: singletons_) {
333         const auto& singleton_entry = *id_singleton_entry.second;
334         if (singleton_entry.state != detail::SingletonEntryState::Dead) {
335           throw std::runtime_error(
336             "Singleton created before registration was complete.");
337         }
338       }
339     }
340
341     registrationComplete_ = true;
342   }
343
344   // Destroy all singletons; when complete, the vault can't create
345   // singletons once again until reenableInstances() is called.
346   void destroyInstances();
347
348   // Enable re-creating singletons after destroyInstances() was called.
349   void reenableInstances();
350
351   // Retrieve a singleton from the vault, creating it if necessary.
352   std::weak_ptr<void> get_weak(detail::TypeDescriptor type) {
353     auto entry = get_entry_create(type);
354     return entry->instance_weak;
355   }
356
357   // This function is inherently racy since we don't hold the
358   // shared_ptr that contains the Singleton.  It is the caller's
359   // responsibility to be sane with this, but it is preferable to use
360   // the weak_ptr interface for true safety.
361   void* get_ptr(detail::TypeDescriptor type) {
362     auto entry = get_entry_create(type);
363     if (UNLIKELY(entry->instance_weak.expired())) {
364       throw std::runtime_error(
365         "Raw pointer to a singleton requested after its destruction.");
366     }
367     return entry->instance_ptr;
368   }
369
370   // For testing; how many registered and living singletons we have.
371   size_t registeredSingletonCount() const {
372     RWSpinLock::ReadHolder rh(&mutex_);
373
374     return singletons_.size();
375   }
376
377   size_t livingSingletonCount() const {
378     RWSpinLock::ReadHolder rh(&mutex_);
379
380     size_t ret = 0;
381     for (const auto& p : singletons_) {
382       if (p.second->state == detail::SingletonEntryState::Living) {
383         ++ret;
384       }
385     }
386
387     return ret;
388   }
389
390   // A well-known vault; you can actually have others, but this is the
391   // default.
392   static SingletonVault* singleton();
393
394  private:
395   // The two stages of life for a vault, as mentioned in the class comment.
396   enum class SingletonVaultState {
397     Running,
398     Quiescing,
399   };
400
401   // Each singleton in the vault can be in two states: dead
402   // (registered but never created), living (CreateFunc returned an instance).
403
404   void stateCheck(SingletonVaultState expected,
405                   const char* msg="Unexpected singleton state change") {
406     if (expected != state_) {
407         throw std::logic_error(msg);
408     }
409   }
410
411   // This method only matters if registrationComplete() is never called.
412   // Otherwise destroyInstances is scheduled to be executed atexit.
413   //
414   // Initializes static object, which calls destroyInstances on destruction.
415   // Used to have better deletion ordering with singleton not managed by
416   // folly::Singleton. The desruction will happen in the following order:
417   // 1. Singletons, not managed by folly::Singleton, which were created after
418   //    any of the singletons managed by folly::Singleton was requested.
419   // 2. All singletons managed by folly::Singleton
420   // 3. Singletons, not managed by folly::Singleton, which were created before
421   //    any of the singletons managed by folly::Singleton was requested.
422   static void scheduleDestroyInstances();
423
424   detail::SingletonEntry* get_entry(detail::TypeDescriptor type) {
425     RWSpinLock::ReadHolder rh(&mutex_);
426
427     auto it = singletons_.find(type);
428     if (it == singletons_.end()) {
429       throw std::out_of_range(std::string("non-existent singleton: ") +
430                               type.name());
431     }
432
433     return it->second.get();
434   }
435
436   // Get a pointer to the living SingletonEntry for the specified
437   // type.  The singleton is created as part of this function, if
438   // necessary.
439   detail::SingletonEntry* get_entry_create(detail::TypeDescriptor type) {
440     auto entry = get_entry(type);
441
442     if (LIKELY(entry->state == detail::SingletonEntryState::Living)) {
443       return entry;
444     }
445
446     // There's no synchronization here, so we may not see the current value
447     // for creating_thread if it was set by other thread, but we only care about
448     // it if it was set by current thread anyways.
449     if (entry->creating_thread == std::this_thread::get_id()) {
450       throw std::out_of_range(std::string("circular singleton dependency: ") +
451                               type.name());
452     }
453
454     std::lock_guard<std::mutex> entry_lock(entry->mutex);
455
456     if (entry->state == detail::SingletonEntryState::Living) {
457       return entry;
458     }
459
460     entry->creating_thread = std::this_thread::get_id();
461
462     RWSpinLock::ReadHolder rh(&stateMutex_);
463     if (state_ == SingletonVaultState::Quiescing) {
464       entry->creating_thread = std::thread::id();
465       return entry;
466     }
467
468     // Can't use make_shared -- no support for a custom deleter, sadly.
469     auto instance = std::shared_ptr<void>(entry->create(), entry->teardown);
470
471     // We should schedule destroyInstances() only after the singleton was
472     // created. This will ensure it will be destroyed before singletons,
473     // not managed by folly::Singleton, which were initialized in its
474     // constructor
475     scheduleDestroyInstances();
476
477     entry->instance = instance;
478     entry->instance_weak = instance;
479     entry->instance_ptr = instance.get();
480     entry->creating_thread = std::thread::id();
481
482     // This has to be the last step, because once state is Living other threads
483     // may access instance and instance_weak w/o synchronization.
484     entry->state.store(detail::SingletonEntryState::Living);
485
486     {
487       RWSpinLock::WriteHolder wh(&mutex_);
488       creation_order_.push_back(type);
489     }
490     return entry;
491   }
492
493   typedef std::unique_ptr<detail::SingletonEntry> SingletonEntryPtr;
494   typedef std::unordered_map<detail::TypeDescriptor,
495                              SingletonEntryPtr,
496                              detail::TypeDescriptorHasher> SingletonMap;
497
498   /* Destroy and clean-up one singleton. Must be invoked while holding
499    * a read lock on mutex_.
500    * @param typeDescriptor - the type key for the removed singleton.
501    */
502   void destroyInstance(SingletonMap::iterator entry_it);
503
504   mutable folly::RWSpinLock mutex_;
505   SingletonMap singletons_;
506   std::vector<detail::TypeDescriptor> creation_order_;
507   SingletonVaultState state_{SingletonVaultState::Running};
508   bool registrationComplete_{false};
509   folly::RWSpinLock stateMutex_;
510   Type type_{Type::Relaxed};
511 };
512
513 // This is the wrapper class that most users actually interact with.
514 // It allows for simple access to registering and instantiating
515 // singletons.  Create instances of this class in the global scope of
516 // type Singleton<T> to register your singleton for later access via
517 // Singleton<T>::get().
518 template <typename T>
519 class Singleton {
520  public:
521   typedef std::function<T*(void)> CreateFunc;
522   typedef std::function<void(T*)> TeardownFunc;
523
524   // Generally your program life cycle should be fine with calling
525   // get() repeatedly rather than saving the reference, and then not
526   // call get() during process shutdown.
527   static T* get(SingletonVault* vault = nullptr /* for testing */) {
528     return get_ptr({typeid(T), ""}, vault);
529   }
530
531   static T* get(const char* name,
532                 SingletonVault* vault = nullptr /* for testing */) {
533     return get_ptr({typeid(T), name}, vault);
534   }
535
536   T* get_fast() {
537     if (LIKELY(entry_->state == detail::SingletonEntryState::Living)) {
538       return reinterpret_cast<T*>(entry_->instance_ptr);
539     } else {
540       return get(type_descriptor_.name_raw().c_str(), vault_);
541     }
542   }
543
544   // If, however, you do need to hold a reference to the specific
545   // singleton, you can try to do so with a weak_ptr.  Avoid this when
546   // possible but the inability to lock the weak pointer can be a
547   // signal that the vault has been destroyed.
548   static std::weak_ptr<T> get_weak(
549       SingletonVault* vault = nullptr /* for testing */) {
550     return get_weak("", vault);
551   }
552
553   static std::weak_ptr<T> get_weak(
554       const char* name, SingletonVault* vault = nullptr /* for testing */) {
555     auto weak_void_ptr =
556       (vault ?: SingletonVault::singleton())->get_weak({typeid(T), name});
557
558     // This is ugly and inefficient, but there's no other way to do it, because
559     // there's no static_pointer_cast for weak_ptr.
560     auto shared_void_ptr = weak_void_ptr.lock();
561     if (!shared_void_ptr) {
562       return std::weak_ptr<T>();
563     }
564     return std::static_pointer_cast<T>(shared_void_ptr);
565   }
566
567   std::weak_ptr<T> get_weak_fast() {
568     if (LIKELY(entry_->state == detail::SingletonEntryState::Living)) {
569       // This is ugly and inefficient, but there's no other way to do it,
570       // because there's no static_pointer_cast for weak_ptr.
571       auto shared_void_ptr = entry_->instance_weak.lock();
572       if (!shared_void_ptr) {
573         return std::weak_ptr<T>();
574       }
575       return std::static_pointer_cast<T>(shared_void_ptr);
576     } else {
577       return get_weak(type_descriptor_.name_raw().c_str(), vault_);
578     }
579   }
580
581   // Allow the Singleton<t> instance to also retrieve the underlying
582   // singleton, if desired.
583   T* ptr() { return get_ptr(type_descriptor_, vault_); }
584   T& operator*() { return *ptr(); }
585   T* operator->() { return ptr(); }
586
587   template <typename CreateFunc = std::nullptr_t>
588   explicit Singleton(CreateFunc c = nullptr,
589                      Singleton::TeardownFunc t = nullptr,
590                      SingletonVault* vault = nullptr /* for testing */)
591       : Singleton({typeid(T), ""}, c, t, vault) {}
592
593   template <typename CreateFunc = std::nullptr_t>
594   explicit Singleton(const char* name,
595                      CreateFunc c = nullptr,
596                      Singleton::TeardownFunc t = nullptr,
597                      SingletonVault* vault = nullptr /* for testing */)
598       : Singleton({typeid(T), name}, c, t, vault) {}
599
600   /**
601   * Construct and inject a mock singleton which should be used only from tests.
602   * See overloaded method for more details.
603   */
604   template <typename CreateFunc = std::nullptr_t>
605   static void make_mock(CreateFunc c = nullptr,
606                      typename Singleton<T>::TeardownFunc t = nullptr,
607                      SingletonVault* vault = nullptr /* for testing */) {
608
609     make_mock("", c, t, vault);
610   }
611
612   /**
613   * Construct and inject a mock singleton which should be used only from tests.
614   * Unlike regular singletons which are initialized once per process lifetime,
615   * mock singletons live for the duration of a test. This means that one process
616   * running multiple tests can initialize and register the same singleton
617   * multiple times. This functionality should be used only from tests
618   * since it relaxes validation and performance in order to be able to perform
619   * the injection. The returned mock singleton is functionality identical to
620   * regular singletons.
621   */
622   template <typename CreateFunc = std::nullptr_t>
623   static void make_mock(const char* name,
624                      CreateFunc c = nullptr,
625                      typename Singleton<T>::TeardownFunc t = nullptr,
626                      SingletonVault* vault = nullptr /* for testing */ ) {
627
628     Singleton<T> mockSingleton({typeid(T), name}, c, t, vault, false);
629     mockSingleton.vault_->registerMockSingleton(
630       mockSingleton.type_descriptor_,
631       c,
632       getTeardownFunc(t));
633   }
634
635  private:
636   explicit Singleton(detail::TypeDescriptor type,
637                      std::nullptr_t,
638                      Singleton::TeardownFunc t,
639                      SingletonVault* vault,
640                      bool registerSingleton = true) :
641       Singleton (type,
642                  []() { return new T; },
643                  std::move(t),
644                  vault,
645                  registerSingleton) {
646   }
647
648   explicit Singleton(detail::TypeDescriptor type,
649                      Singleton::CreateFunc c,
650                      Singleton::TeardownFunc t,
651                      SingletonVault* vault,
652                      bool registerSingleton = true)
653       : type_descriptor_(type) {
654     if (c == nullptr) {
655       throw std::logic_error(
656         "nullptr_t should be passed if you want T to be default constructed");
657     }
658
659     if (vault == nullptr) {
660       vault = SingletonVault::singleton();
661     }
662
663     vault_ = vault;
664     if (registerSingleton) {
665       entry_ = &(vault->registerSingleton(type, c, getTeardownFunc(t)));
666     }
667   }
668
669   static inline void make_mock(const char* name,
670                      std::nullptr_t c,
671                      typename Singleton<T>::TeardownFunc t = nullptr,
672                      SingletonVault* vault = nullptr /* for testing */ ) {
673     make_mock(name, []() { return new T; }, std::move(t), vault);
674   }
675
676
677 private:
678   // Construct SingletonVault::TeardownFunc.
679   static SingletonVault::TeardownFunc getTeardownFunc(
680       Singleton<T>::TeardownFunc t) {
681     SingletonVault::TeardownFunc teardown;
682     if (t == nullptr) {
683       teardown = [](void* v) { delete static_cast<T*>(v); };
684     } else {
685       teardown = [t](void* v) { t(static_cast<T*>(v)); };
686     }
687
688     return teardown;
689   }
690
691   static T* get_ptr(detail::TypeDescriptor type_descriptor = {typeid(T), ""},
692                     SingletonVault* vault = nullptr /* for testing */) {
693     return static_cast<T*>(
694         (vault ?: SingletonVault::singleton())->get_ptr(type_descriptor));
695   }
696
697   // Don't use this function, it's private for a reason!  Using it
698   // would defeat the *entire purpose* of the vault in that we lose
699   // the ability to guarantee that, after a destroyInstances is
700   // called, all instances are, in fact, destroyed.  You should use
701   // weak_ptr if you need to hold a reference to the singleton and
702   // guarantee briefly that it exists.
703   //
704   // Yes, you can just get the weak pointer and lock it, but hopefully
705   // if you have taken the time to read this far, you see why that
706   // would be bad.
707   static std::shared_ptr<T> get_shared(
708       detail::TypeDescriptor type_descriptor = {typeid(T), ""},
709       SingletonVault* vault = nullptr /* for testing */) {
710     return std::static_pointer_cast<T>(
711       (vault ?: SingletonVault::singleton())->get_weak(type_descriptor).lock());
712   }
713
714   detail::TypeDescriptor type_descriptor_;
715   // This is pointing to SingletonEntry paired with this singleton object. This
716   // is never reset, so each SingletonEntry should never be destroyed.
717   // We rely on the fact that Singleton destructor won't reset this pointer, so
718   // it can be "safely" used even after static Singleton object is destroyed.
719   detail::SingletonEntry* entry_;
720   SingletonVault* vault_;
721 };
722
723 }