Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
michael@0 | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 2 | // Use of this source code is governed by a BSD-style license that can be |
michael@0 | 3 | // found in the LICENSE file. |
michael@0 | 4 | |
michael@0 | 5 | // The LazyInstance<Type, Traits> class manages a single instance of Type, |
michael@0 | 6 | // which will be lazily created on the first time it's accessed. This class is |
michael@0 | 7 | // useful for places you would normally use a function-level static, but you |
michael@0 | 8 | // need to have guaranteed thread-safety. The Type constructor will only ever |
michael@0 | 9 | // be called once, even if two threads are racing to create the object. Get() |
michael@0 | 10 | // and Pointer() will always return the same, completely initialized instance. |
michael@0 | 11 | // When the instance is constructed it is registered with AtExitManager. The |
michael@0 | 12 | // destructor will be called on program exit. |
michael@0 | 13 | // |
michael@0 | 14 | // LazyInstance is completely thread safe, assuming that you create it safely. |
michael@0 | 15 | // The class was designed to be POD initialized, so it shouldn't require a |
michael@0 | 16 | // static constructor. It really only makes sense to declare a LazyInstance as |
michael@0 | 17 | // a global variable using the LAZY_INSTANCE_INITIALIZER initializer. |
michael@0 | 18 | // |
michael@0 | 19 | // LazyInstance is similar to Singleton, except it does not have the singleton |
michael@0 | 20 | // property. You can have multiple LazyInstance's of the same type, and each |
michael@0 | 21 | // will manage a unique instance. It also preallocates the space for Type, as |
michael@0 | 22 | // to avoid allocating the Type instance on the heap. This may help with the |
michael@0 | 23 | // performance of creating the instance, and reducing heap fragmentation. This |
michael@0 | 24 | // requires that Type be a complete type so we can determine the size. |
michael@0 | 25 | // |
michael@0 | 26 | // Example usage: |
michael@0 | 27 | // static LazyInstance<MyClass> my_instance = LAZY_INSTANCE_INITIALIZER; |
michael@0 | 28 | // void SomeMethod() { |
michael@0 | 29 | // my_instance.Get().SomeMethod(); // MyClass::SomeMethod() |
michael@0 | 30 | // |
michael@0 | 31 | // MyClass* ptr = my_instance.Pointer(); |
michael@0 | 32 | // ptr->DoDoDo(); // MyClass::DoDoDo |
michael@0 | 33 | // } |
michael@0 | 34 | |
michael@0 | 35 | #ifndef BASE_LAZY_INSTANCE_H_ |
michael@0 | 36 | #define BASE_LAZY_INSTANCE_H_ |
michael@0 | 37 | |
michael@0 | 38 | #include <new> // For placement new. |
michael@0 | 39 | |
michael@0 | 40 | #include "base/atomicops.h" |
michael@0 | 41 | #include "base/base_export.h" |
michael@0 | 42 | #include "base/basictypes.h" |
michael@0 | 43 | #include "base/debug/leak_annotations.h" |
michael@0 | 44 | #include "base/logging.h" |
michael@0 | 45 | #include "base/memory/aligned_memory.h" |
michael@0 | 46 | #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
michael@0 | 47 | #include "base/threading/thread_restrictions.h" |
michael@0 | 48 | |
michael@0 | 49 | // LazyInstance uses its own struct initializer-list style static |
michael@0 | 50 | // initialization, as base's LINKER_INITIALIZED requires a constructor and on |
michael@0 | 51 | // some compilers (notably gcc 4.4) this still ends up needing runtime |
michael@0 | 52 | // initialization. |
michael@0 | 53 | #define LAZY_INSTANCE_INITIALIZER {0} |
michael@0 | 54 | |
michael@0 | 55 | namespace base { |
michael@0 | 56 | |
michael@0 | 57 | template <typename Type> |
michael@0 | 58 | struct DefaultLazyInstanceTraits { |
michael@0 | 59 | static const bool kRegisterOnExit = true; |
michael@0 | 60 | static const bool kAllowedToAccessOnNonjoinableThread = false; |
michael@0 | 61 | |
michael@0 | 62 | static Type* New(void* instance) { |
michael@0 | 63 | DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (ALIGNOF(Type) - 1), 0u) |
michael@0 | 64 | << ": Bad boy, the buffer passed to placement new is not aligned!\n" |
michael@0 | 65 | "This may break some stuff like SSE-based optimizations assuming the " |
michael@0 | 66 | "<Type> objects are word aligned."; |
michael@0 | 67 | // Use placement new to initialize our instance in our preallocated space. |
michael@0 | 68 | // The parenthesis is very important here to force POD type initialization. |
michael@0 | 69 | return new (instance) Type(); |
michael@0 | 70 | } |
michael@0 | 71 | static void Delete(Type* instance) { |
michael@0 | 72 | // Explicitly call the destructor. |
michael@0 | 73 | instance->~Type(); |
michael@0 | 74 | } |
michael@0 | 75 | }; |
michael@0 | 76 | |
michael@0 | 77 | // We pull out some of the functionality into non-templated functions, so we |
michael@0 | 78 | // can implement the more complicated pieces out of line in the .cc file. |
michael@0 | 79 | namespace internal { |
michael@0 | 80 | |
michael@0 | 81 | // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: |
michael@0 | 82 | // base::LazyInstance<T>::Leaky my_leaky_lazy_instance; |
michael@0 | 83 | // instead of: |
michael@0 | 84 | // base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> > |
michael@0 | 85 | // my_leaky_lazy_instance; |
michael@0 | 86 | // (especially when T is MyLongTypeNameImplClientHolderFactory). |
michael@0 | 87 | // Only use this internal::-qualified verbose form to extend this traits class |
michael@0 | 88 | // (depending on its implementation details). |
michael@0 | 89 | template <typename Type> |
michael@0 | 90 | struct LeakyLazyInstanceTraits { |
michael@0 | 91 | static const bool kRegisterOnExit = false; |
michael@0 | 92 | static const bool kAllowedToAccessOnNonjoinableThread = true; |
michael@0 | 93 | |
michael@0 | 94 | static Type* New(void* instance) { |
michael@0 | 95 | ANNOTATE_SCOPED_MEMORY_LEAK; |
michael@0 | 96 | return DefaultLazyInstanceTraits<Type>::New(instance); |
michael@0 | 97 | } |
michael@0 | 98 | static void Delete(Type* instance) { |
michael@0 | 99 | } |
michael@0 | 100 | }; |
michael@0 | 101 | |
michael@0 | 102 | // Our AtomicWord doubles as a spinlock, where a value of |
michael@0 | 103 | // kBeingCreatedMarker means the spinlock is being held for creation. |
michael@0 | 104 | static const subtle::AtomicWord kLazyInstanceStateCreating = 1; |
michael@0 | 105 | |
michael@0 | 106 | // Check if instance needs to be created. If so return true otherwise |
michael@0 | 107 | // if another thread has beat us, wait for instance to be created and |
michael@0 | 108 | // return false. |
michael@0 | 109 | BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); |
michael@0 | 110 | |
michael@0 | 111 | // After creating an instance, call this to register the dtor to be called |
michael@0 | 112 | // at program exit and to update the atomic state to hold the |new_instance| |
michael@0 | 113 | BASE_EXPORT void CompleteLazyInstance(subtle::AtomicWord* state, |
michael@0 | 114 | subtle::AtomicWord new_instance, |
michael@0 | 115 | void* lazy_instance, |
michael@0 | 116 | void (*dtor)(void*)); |
michael@0 | 117 | |
michael@0 | 118 | } // namespace internal |
michael@0 | 119 | |
michael@0 | 120 | template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > |
michael@0 | 121 | class LazyInstance { |
michael@0 | 122 | public: |
michael@0 | 123 | // Do not define a destructor, as doing so makes LazyInstance a |
michael@0 | 124 | // non-POD-struct. We don't want that because then a static initializer will |
michael@0 | 125 | // be created to register the (empty) destructor with atexit() under MSVC, for |
michael@0 | 126 | // example. We handle destruction of the contained Type class explicitly via |
michael@0 | 127 | // the OnExit member function, where needed. |
michael@0 | 128 | // ~LazyInstance() {} |
michael@0 | 129 | |
michael@0 | 130 | // Convenience typedef to avoid having to repeat Type for leaky lazy |
michael@0 | 131 | // instances. |
michael@0 | 132 | typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type> > Leaky; |
michael@0 | 133 | |
michael@0 | 134 | Type& Get() { |
michael@0 | 135 | return *Pointer(); |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | Type* Pointer() { |
michael@0 | 139 | #ifndef NDEBUG |
michael@0 | 140 | // Avoid making TLS lookup on release builds. |
michael@0 | 141 | if (!Traits::kAllowedToAccessOnNonjoinableThread) |
michael@0 | 142 | ThreadRestrictions::AssertSingletonAllowed(); |
michael@0 | 143 | #endif |
michael@0 | 144 | // If any bit in the created mask is true, the instance has already been |
michael@0 | 145 | // fully constructed. |
michael@0 | 146 | static const subtle::AtomicWord kLazyInstanceCreatedMask = |
michael@0 | 147 | ~internal::kLazyInstanceStateCreating; |
michael@0 | 148 | |
michael@0 | 149 | // We will hopefully have fast access when the instance is already created. |
michael@0 | 150 | // Since a thread sees private_instance_ == 0 or kLazyInstanceStateCreating |
michael@0 | 151 | // at most once, the load is taken out of NeedsInstance() as a fast-path. |
michael@0 | 152 | // The load has acquire memory ordering as a thread which sees |
michael@0 | 153 | // private_instance_ > creating needs to acquire visibility over |
michael@0 | 154 | // the associated data (private_buf_). Pairing Release_Store is in |
michael@0 | 155 | // CompleteLazyInstance(). |
michael@0 | 156 | subtle::AtomicWord value = subtle::Acquire_Load(&private_instance_); |
michael@0 | 157 | if (!(value & kLazyInstanceCreatedMask) && |
michael@0 | 158 | internal::NeedsLazyInstance(&private_instance_)) { |
michael@0 | 159 | // Create the instance in the space provided by |private_buf_|. |
michael@0 | 160 | value = reinterpret_cast<subtle::AtomicWord>( |
michael@0 | 161 | Traits::New(private_buf_.void_data())); |
michael@0 | 162 | internal::CompleteLazyInstance(&private_instance_, value, this, |
michael@0 | 163 | Traits::kRegisterOnExit ? OnExit : NULL); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | // This annotation helps race detectors recognize correct lock-less |
michael@0 | 167 | // synchronization between different threads calling Pointer(). |
michael@0 | 168 | // We suggest dynamic race detection tool that "Traits::New" above |
michael@0 | 169 | // and CompleteLazyInstance(...) happens before "return instance()" below. |
michael@0 | 170 | // See the corresponding HAPPENS_BEFORE in CompleteLazyInstance(...). |
michael@0 | 171 | ANNOTATE_HAPPENS_AFTER(&private_instance_); |
michael@0 | 172 | return instance(); |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | bool operator==(Type* p) { |
michael@0 | 176 | switch (subtle::NoBarrier_Load(&private_instance_)) { |
michael@0 | 177 | case 0: |
michael@0 | 178 | return p == NULL; |
michael@0 | 179 | case internal::kLazyInstanceStateCreating: |
michael@0 | 180 | return static_cast<void*>(p) == private_buf_.void_data(); |
michael@0 | 181 | default: |
michael@0 | 182 | return p == instance(); |
michael@0 | 183 | } |
michael@0 | 184 | } |
michael@0 | 185 | |
michael@0 | 186 | // Effectively private: member data is only public to allow the linker to |
michael@0 | 187 | // statically initialize it and to maintain a POD class. DO NOT USE FROM |
michael@0 | 188 | // OUTSIDE THIS CLASS. |
michael@0 | 189 | |
michael@0 | 190 | subtle::AtomicWord private_instance_; |
michael@0 | 191 | // Preallocated space for the Type instance. |
michael@0 | 192 | base::AlignedMemory<sizeof(Type), ALIGNOF(Type)> private_buf_; |
michael@0 | 193 | |
michael@0 | 194 | private: |
michael@0 | 195 | Type* instance() { |
michael@0 | 196 | return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_)); |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | // Adapter function for use with AtExit. This should be called single |
michael@0 | 200 | // threaded, so don't synchronize across threads. |
michael@0 | 201 | // Calling OnExit while the instance is in use by other threads is a mistake. |
michael@0 | 202 | static void OnExit(void* lazy_instance) { |
michael@0 | 203 | LazyInstance<Type, Traits>* me = |
michael@0 | 204 | reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); |
michael@0 | 205 | Traits::Delete(me->instance()); |
michael@0 | 206 | subtle::NoBarrier_Store(&me->private_instance_, 0); |
michael@0 | 207 | } |
michael@0 | 208 | }; |
michael@0 | 209 | |
michael@0 | 210 | } // namespace base |
michael@0 | 211 | |
michael@0 | 212 | #endif // BASE_LAZY_INSTANCE_H_ |