tor-browser

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

lazy_instance.h (7829B)


      1 // Copyright 2012 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 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DEPRECATED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      6 // Please don't introduce new instances of LazyInstance<T>. Use a function-local
      7 // 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 // The LazyInstance<Type, Traits> class manages a single instance of Type,
     16 // which will be lazily created on the first time it's accessed.  This class is
     17 // useful for places you would normally use a function-level static, but you
     18 // need to have guaranteed thread-safety.  The Type constructor will only ever
     19 // be called once, even if two threads are racing to create the object.  Get()
     20 // and Pointer() will always return the same, completely initialized instance.
     21 // When the instance is constructed it is registered with AtExitManager.  The
     22 // destructor will be called on program exit.
     23 //
     24 // LazyInstance is completely thread safe, assuming that you create it safely.
     25 // The class was designed to be POD initialized, so it shouldn't require a
     26 // static constructor.  It really only makes sense to declare a LazyInstance as
     27 // a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
     28 //
     29 // LazyInstance is similar to Singleton, except it does not have the singleton
     30 // property.  You can have multiple LazyInstance's of the same type, and each
     31 // will manage a unique instance.  It also preallocates the space for Type, as
     32 // to avoid allocating the Type instance on the heap.  This may help with the
     33 // performance of creating the instance, and reducing heap fragmentation.  This
     34 // requires that Type be a complete type so we can determine the size.
     35 //
     36 // Example usage:
     37 //   static LazyInstance<MyClass>::Leaky inst = LAZY_INSTANCE_INITIALIZER;
     38 //   void SomeMethod() {
     39 //     inst.Get().SomeMethod();  // MyClass::SomeMethod()
     40 //
     41 //     MyClass* ptr = inst.Pointer();
     42 //     ptr->DoDoDo();  // MyClass::DoDoDo
     43 //   }
     44 
     45 #ifndef BASE_LAZY_INSTANCE_H_
     46 #define BASE_LAZY_INSTANCE_H_
     47 
     48 #include <atomic>
     49 #include <new>  // For placement new.
     50 
     51 #include "base/check_op.h"
     52 #include "base/dcheck_is_on.h"
     53 #include "base/debug/leak_annotations.h"
     54 #include "base/lazy_instance_helpers.h"
     55 #include "base/threading/thread_restrictions.h"
     56 #include "build/build_config.h"
     57 
     58 // LazyInstance uses its own struct initializer-list style static
     59 // initialization, which does not require a constructor.
     60 #define LAZY_INSTANCE_INITIALIZER {}
     61 
     62 namespace base {
     63 
     64 template <typename Type>
     65 struct LazyInstanceTraitsBase {
     66  static Type* New(void* instance) {
     67    DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (alignof(Type) - 1), 0u);
     68    // Use placement new to initialize our instance in our preallocated space.
     69    // The parenthesis is very important here to force POD type initialization.
     70    return new (instance) Type();
     71  }
     72 
     73  static void CallDestructor(Type* instance) {
     74    // Explicitly call the destructor.
     75    instance->~Type();
     76  }
     77 };
     78 
     79 // We pull out some of the functionality into non-templated functions, so we
     80 // can implement the more complicated pieces out of line in the .cc file.
     81 namespace internal {
     82 
     83 // This traits class causes destruction the contained Type at process exit via
     84 // AtExitManager. This is probably generally not what you want. Instead, prefer
     85 // Leaky below.
     86 template <typename Type>
     87 struct DestructorAtExitLazyInstanceTraits {
     88  static const bool kRegisterOnExit = true;
     89 #if DCHECK_IS_ON()
     90  static const bool kAllowedToAccessOnNonjoinableThread = false;
     91 #endif
     92 
     93  static Type* New(void* instance) {
     94    return LazyInstanceTraitsBase<Type>::New(instance);
     95  }
     96 
     97  static void Delete(Type* instance) {
     98    LazyInstanceTraitsBase<Type>::CallDestructor(instance);
     99  }
    100 };
    101 
    102 // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.:
    103 // base::LazyInstance<T>::Leaky my_leaky_lazy_instance;
    104 // instead of:
    105 // base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> >
    106 // my_leaky_lazy_instance;
    107 // (especially when T is MyLongTypeNameImplClientHolderFactory).
    108 // Only use this internal::-qualified verbose form to extend this traits class
    109 // (depending on its implementation details).
    110 template <typename Type>
    111 struct LeakyLazyInstanceTraits {
    112  static const bool kRegisterOnExit = false;
    113 #if DCHECK_IS_ON()
    114  static const bool kAllowedToAccessOnNonjoinableThread = true;
    115 #endif
    116 
    117  static Type* New(void* instance) {
    118    ANNOTATE_SCOPED_MEMORY_LEAK;
    119    return LazyInstanceTraitsBase<Type>::New(instance);
    120  }
    121  static void Delete(Type* instance) {
    122  }
    123 };
    124 
    125 template <typename Type>
    126 struct ErrorMustSelectLazyOrDestructorAtExitForLazyInstance {};
    127 
    128 }  // namespace internal
    129 
    130 template <
    131    typename Type,
    132    typename Traits =
    133        internal::ErrorMustSelectLazyOrDestructorAtExitForLazyInstance<Type>>
    134 class LazyInstance {
    135 public:
    136  // Do not define a destructor, as doing so makes LazyInstance a
    137  // non-POD-struct. We don't want that because then a static initializer will
    138  // be created to register the (empty) destructor with atexit() under MSVC, for
    139  // example. We handle destruction of the contained Type class explicitly via
    140  // the OnExit member function, where needed.
    141  // ~LazyInstance() {}
    142 
    143  // Convenience typedef to avoid having to repeat Type for leaky lazy
    144  // instances.
    145  typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type>> Leaky;
    146  typedef LazyInstance<Type, internal::DestructorAtExitLazyInstanceTraits<Type>>
    147      DestructorAtExit;
    148 
    149  Type& Get() {
    150    return *Pointer();
    151  }
    152 
    153  Type* Pointer() {
    154 #if DCHECK_IS_ON()
    155    if (!Traits::kAllowedToAccessOnNonjoinableThread)
    156      internal::AssertSingletonAllowed();
    157 #endif
    158 
    159    return subtle::GetOrCreateLazyPointer(
    160        private_instance_, &Traits::New, private_buf_,
    161        Traits::kRegisterOnExit ? OnExit : nullptr, this);
    162  }
    163 
    164  // Returns true if the lazy instance has been created.  Unlike Get() and
    165  // Pointer(), calling IsCreated() will not instantiate the object of Type.
    166  bool IsCreated() {
    167    // Return true (i.e. "created") if |private_instance_| is either being
    168    // created right now (i.e. |private_instance_| has value of
    169    // internal::kLazyInstanceStateCreating) or was already created (i.e.
    170    // |private_instance_| has any other non-zero value).
    171    return 0 != private_instance_.load(std::memory_order_relaxed);
    172  }
    173 
    174  // MSVC gives a warning that the alignment expands the size of the
    175  // LazyInstance struct to make the size a multiple of the alignment. This
    176  // is expected in this case.
    177 #if BUILDFLAG(IS_WIN)
    178 #pragma warning(push)
    179 #pragma warning(disable : 4324)
    180 #endif
    181 
    182  // Effectively private: member data is only public to allow the linker to
    183  // statically initialize it and to maintain a POD class. DO NOT USE FROM
    184  // OUTSIDE THIS CLASS.
    185  std::atomic<uintptr_t> private_instance_;
    186 
    187  // Preallocated space for the Type instance.
    188  alignas(Type) char private_buf_[sizeof(Type)];
    189 
    190 #if BUILDFLAG(IS_WIN)
    191 #pragma warning(pop)
    192 #endif
    193 
    194 private:
    195  Type* instance() {
    196    return reinterpret_cast<Type*>(
    197        private_instance_.load(std::memory_order_relaxed));
    198  }
    199 
    200  // Adapter function for use with AtExit.  This should be called single
    201  // threaded, so don't synchronize across threads.
    202  // Calling OnExit while the instance is in use by other threads is a mistake.
    203  static void OnExit(void* lazy_instance) {
    204    LazyInstance<Type, Traits>* me =
    205        reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
    206    Traits::Delete(me->instance());
    207    me->private_instance_.store(0, std::memory_order_relaxed);
    208  }
    209 };
    210 
    211 }  // namespace base
    212 
    213 #endif  // BASE_LAZY_INSTANCE_H_