tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

singleton.h (10590B)


      1 // Copyright 2011 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 //
      5 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      6 // PLEASE READ: Do you really need a singleton? If possible, use a
      7 // function-local static of type base::NoDestructor<T> instead:
      8 //
      9 // Factory& Factory::GetInstance() {
     10 //   static base::NoDestructor<Factory> instance;
     11 //   return *instance;
     12 // }
     13 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     14 //
     15 // Singletons make it hard to determine the lifetime of an object, which can
     16 // lead to buggy code and spurious crashes.
     17 //
     18 // Instead of adding another singleton into the mix, try to identify either:
     19 //   a) An existing singleton that can manage your object's lifetime
     20 //   b) Locations where you can deterministically create the object and pass
     21 //      into other objects
     22 //
     23 // If you absolutely need a singleton, please keep them as trivial as possible
     24 // and ideally a leaf dependency. Singletons get problematic when they attempt
     25 // to do too much in their destructor or have circular dependencies.
     26 
     27 #ifndef BASE_MEMORY_SINGLETON_H_
     28 #define BASE_MEMORY_SINGLETON_H_
     29 
     30 #include <atomic>
     31 
     32 #include "base/dcheck_is_on.h"
     33 #include "base/lazy_instance_helpers.h"
     34 #include "base/threading/thread_restrictions.h"
     35 
     36 namespace base {
     37 
     38 // Default traits for Singleton<Type>. Calls operator new and operator delete on
     39 // the object. Registers automatic deletion at process exit.
     40 // Overload if you need arguments or another memory allocation function.
     41 template<typename Type>
     42 struct DefaultSingletonTraits {
     43  // Allocates the object.
     44  static Type* New() {
     45    // The parenthesis is very important here; it forces POD type
     46    // initialization.
     47    return new Type();
     48  }
     49 
     50  // Destroys the object.
     51  static void Delete(Type* x) {
     52    delete x;
     53  }
     54 
     55  // Set to true to automatically register deletion of the object on process
     56  // exit. See below for the required call that makes this happen.
     57  static const bool kRegisterAtExit = true;
     58 
     59 #if DCHECK_IS_ON()
     60  // Set to false to disallow access on a non-joinable thread.  This is
     61  // different from kRegisterAtExit because StaticMemorySingletonTraits allows
     62  // access on non-joinable threads, and gracefully handles this.
     63  static const bool kAllowedToAccessOnNonjoinableThread = false;
     64 #endif
     65 };
     66 
     67 
     68 // Alternate traits for use with the Singleton<Type>.  Identical to
     69 // DefaultSingletonTraits except that the Singleton will not be cleaned up
     70 // at exit.
     71 template<typename Type>
     72 struct LeakySingletonTraits : public DefaultSingletonTraits<Type> {
     73  static const bool kRegisterAtExit = false;
     74 #if DCHECK_IS_ON()
     75  static const bool kAllowedToAccessOnNonjoinableThread = true;
     76 #endif
     77 };
     78 
     79 // Alternate traits for use with the Singleton<Type>.  Allocates memory
     80 // for the singleton instance from a static buffer.  The singleton will
     81 // be cleaned up at exit, but can't be revived after destruction unless
     82 // the ResurrectForTesting() method is called.
     83 //
     84 // This is useful for a certain category of things, notably logging and
     85 // tracing, where the singleton instance is of a type carefully constructed to
     86 // be safe to access post-destruction.
     87 // In logging and tracing you'll typically get stray calls at odd times, like
     88 // during static destruction, thread teardown and the like, and there's a
     89 // termination race on the heap-based singleton - e.g. if one thread calls
     90 // get(), but then another thread initiates AtExit processing, the first thread
     91 // may call into an object residing in unallocated memory. If the instance is
     92 // allocated from the data segment, then this is survivable.
     93 //
     94 // The destructor is to deallocate system resources, in this case to unregister
     95 // a callback the system will invoke when logging levels change. Note that
     96 // this is also used in e.g. Chrome Frame, where you have to allow for the
     97 // possibility of loading briefly into someone else's process space, and
     98 // so leaking is not an option, as that would sabotage the state of your host
     99 // process once you've unloaded.
    100 template <typename Type>
    101 struct StaticMemorySingletonTraits {
    102  // WARNING: User has to support a New() which returns null.
    103  static Type* New() {
    104    // Only constructs once and returns pointer; otherwise returns null.
    105    if (dead_.exchange(true, std::memory_order_relaxed))
    106      return nullptr;
    107 
    108    return new (buffer_) Type();
    109  }
    110 
    111  static void Delete(Type* p) {
    112    if (p)
    113      p->Type::~Type();
    114  }
    115 
    116  static const bool kRegisterAtExit = true;
    117 
    118 #if DCHECK_IS_ON()
    119  static const bool kAllowedToAccessOnNonjoinableThread = true;
    120 #endif
    121 
    122  static void ResurrectForTesting() {
    123    dead_.store(false, std::memory_order_relaxed);
    124  }
    125 
    126 private:
    127  alignas(Type) static char buffer_[sizeof(Type)];
    128  // Signal the object was already deleted, so it is not revived.
    129  static std::atomic<bool> dead_;
    130 };
    131 
    132 template <typename Type>
    133 alignas(Type) char StaticMemorySingletonTraits<Type>::buffer_[sizeof(Type)];
    134 template <typename Type>
    135 std::atomic<bool> StaticMemorySingletonTraits<Type>::dead_ = false;
    136 
    137 // The Singleton<Type, Traits, DifferentiatingType> class manages a single
    138 // instance of Type which will be created on first use and will be destroyed at
    139 // normal process exit). The Trait::Delete function will not be called on
    140 // abnormal process exit.
    141 //
    142 // DifferentiatingType is used as a key to differentiate two different
    143 // singletons having the same memory allocation functions but serving a
    144 // different purpose. This is mainly used for Locks serving different purposes.
    145 //
    146 // Example usage:
    147 //
    148 // In your header:
    149 //   namespace base {
    150 //   template <typename T>
    151 //   struct DefaultSingletonTraits;
    152 //   }
    153 //   class FooClass {
    154 //    public:
    155 //     static FooClass* GetInstance();  <-- See comment below on this.
    156 //
    157 //     FooClass(const FooClass&) = delete;
    158 //     FooClass& operator=(const FooClass&) = delete;
    159 //
    160 //     void Bar() { ... }
    161 //
    162 //    private:
    163 //     FooClass() { ... }
    164 //     friend struct base::DefaultSingletonTraits<FooClass>;
    165 //   };
    166 //
    167 // In your source file:
    168 //  #include "base/memory/singleton.h"
    169 //  FooClass* FooClass::GetInstance() {
    170 //    return base::Singleton<FooClass>::get();
    171 //  }
    172 //
    173 // Or for leaky singletons:
    174 //  #include "base/memory/singleton.h"
    175 //  FooClass* FooClass::GetInstance() {
    176 //    return base::Singleton<
    177 //        FooClass, base::LeakySingletonTraits<FooClass>>::get();
    178 //  }
    179 //
    180 // And to call methods on FooClass:
    181 //   FooClass::GetInstance()->Bar();
    182 //
    183 // NOTE: The method accessing Singleton<T>::get() has to be named as GetInstance
    184 // and it is important that FooClass::GetInstance() is not inlined in the
    185 // header. This makes sure that when source files from multiple targets include
    186 // this header they don't end up with different copies of the inlined code
    187 // creating multiple copies of the singleton.
    188 //
    189 // Singleton<> has no non-static members and doesn't need to actually be
    190 // instantiated.
    191 //
    192 // This class is itself thread-safe. The underlying Type must of course be
    193 // thread-safe if you want to use it concurrently. Two parameters may be tuned
    194 // depending on the user's requirements.
    195 //
    196 // Glossary:
    197 //   RAE = kRegisterAtExit
    198 //
    199 // On every platform, if Traits::RAE is true, the singleton will be destroyed at
    200 // process exit. More precisely it uses AtExitManager which requires an
    201 // object of this type to be instantiated. AtExitManager mimics the semantics
    202 // of atexit() such as LIFO order but under Windows is safer to call. For more
    203 // information see at_exit.h.
    204 //
    205 // If Traits::RAE is false, the singleton will not be freed at process exit,
    206 // thus the singleton will be leaked if it is ever accessed. Traits::RAE
    207 // shouldn't be false unless absolutely necessary. Remember that the heap where
    208 // the object is allocated may be destroyed by the CRT anyway.
    209 //
    210 // Caveats:
    211 // (a) Every call to get(), operator->() and operator*() incurs some overhead
    212 //     (16ns on my P4/2.8GHz) to check whether the object has already been
    213 //     initialized.  You may wish to cache the result of get(); it will not
    214 //     change.
    215 //
    216 // (b) Your factory function must never throw an exception. This class is not
    217 //     exception-safe.
    218 //
    219 
    220 template <typename Type,
    221          typename Traits = DefaultSingletonTraits<Type>,
    222          typename DifferentiatingType = Type>
    223 class Singleton {
    224 private:
    225  // A class T using the Singleton<T> pattern should declare a GetInstance()
    226  // method and call Singleton::get() from within that. T may also declare a
    227  // GetInstanceIfExists() method to invoke Singleton::GetIfExists().
    228  friend Type;
    229 
    230  // This class is safe to be constructed and copy-constructed since it has no
    231  // member.
    232 
    233  // Returns a pointer to the one true instance of the class.
    234  static Type* get() {
    235 #if DCHECK_IS_ON()
    236    if (!Traits::kAllowedToAccessOnNonjoinableThread)
    237      internal::AssertSingletonAllowed();
    238 #endif
    239 
    240    return subtle::GetOrCreateLazyPointer(
    241        instance_, &CreatorFunc, nullptr,
    242        Traits::kRegisterAtExit ? OnExit : nullptr, nullptr);
    243  }
    244 
    245  // Returns the same result as get() if the instance exists but doesn't
    246  // construct it (and returns null) if it doesn't.
    247  static Type* GetIfExists() {
    248 #if DCHECK_IS_ON()
    249    if (!Traits::kAllowedToAccessOnNonjoinableThread)
    250      internal::AssertSingletonAllowed();
    251 #endif
    252 
    253    if (!instance_.load(std::memory_order_relaxed))
    254      return nullptr;
    255 
    256    // Need to invoke get() nonetheless as some Traits return null after
    257    // destruction (even though |instance_| still holds garbage).
    258    return get();
    259  }
    260 
    261  // Internal method used as an adaptor for GetOrCreateLazyPointer(). Do not use
    262  // outside of that use case.
    263  static Type* CreatorFunc(void* /* creator_arg*/) { return Traits::New(); }
    264 
    265  // Adapter function for use with AtExit().  This should be called single
    266  // threaded, so don't use atomic operations.
    267  // Calling OnExit while singleton is in use by other threads is a mistake.
    268  static void OnExit(void* /*unused*/) {
    269    // AtExit should only ever be register after the singleton instance was
    270    // created.  We should only ever get here with a valid instance_ pointer.
    271    Traits::Delete(
    272        reinterpret_cast<Type*>(instance_.load(std::memory_order_relaxed)));
    273    instance_.store(0, std::memory_order_relaxed);
    274  }
    275  static std::atomic<uintptr_t> instance_;
    276 };
    277 
    278 template <typename Type, typename Traits, typename DifferentiatingType>
    279 std::atomic<uintptr_t> Singleton<Type, Traits, DifferentiatingType>::instance_ =
    280    0;
    281 
    282 }  // namespace base
    283 
    284 #endif  // BASE_MEMORY_SINGLETON_H_