/src/mozilla-central/security/sandbox/chromium/base/lazy_instance.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | // The LazyInstance<Type, Traits> class manages a single instance of Type, |
6 | | // which will be lazily created on the first time it's accessed. This class is |
7 | | // useful for places you would normally use a function-level static, but you |
8 | | // need to have guaranteed thread-safety. The Type constructor will only ever |
9 | | // be called once, even if two threads are racing to create the object. Get() |
10 | | // and Pointer() will always return the same, completely initialized instance. |
11 | | // When the instance is constructed it is registered with AtExitManager. The |
12 | | // destructor will be called on program exit. |
13 | | // |
14 | | // LazyInstance is completely thread safe, assuming that you create it safely. |
15 | | // The class was designed to be POD initialized, so it shouldn't require a |
16 | | // static constructor. It really only makes sense to declare a LazyInstance as |
17 | | // a global variable using the LAZY_INSTANCE_INITIALIZER initializer. |
18 | | // |
19 | | // LazyInstance is similar to Singleton, except it does not have the singleton |
20 | | // property. You can have multiple LazyInstance's of the same type, and each |
21 | | // will manage a unique instance. It also preallocates the space for Type, as |
22 | | // to avoid allocating the Type instance on the heap. This may help with the |
23 | | // performance of creating the instance, and reducing heap fragmentation. This |
24 | | // requires that Type be a complete type so we can determine the size. |
25 | | // |
26 | | // Example usage: |
27 | | // static LazyInstance<MyClass>::Leaky inst = LAZY_INSTANCE_INITIALIZER; |
28 | | // void SomeMethod() { |
29 | | // inst.Get().SomeMethod(); // MyClass::SomeMethod() |
30 | | // |
31 | | // MyClass* ptr = inst.Pointer(); |
32 | | // ptr->DoDoDo(); // MyClass::DoDoDo |
33 | | // } |
34 | | |
35 | | #ifndef BASE_LAZY_INSTANCE_H_ |
36 | | #define BASE_LAZY_INSTANCE_H_ |
37 | | |
38 | | #include <new> // For placement new. |
39 | | |
40 | | #include "base/atomicops.h" |
41 | | #include "base/base_export.h" |
42 | | #include "base/debug/leak_annotations.h" |
43 | | #include "base/logging.h" |
44 | | #include "base/threading/thread_restrictions.h" |
45 | | |
46 | | // LazyInstance uses its own struct initializer-list style static |
47 | | // initialization, as base's LINKER_INITIALIZED requires a constructor and on |
48 | | // some compilers (notably gcc 4.4) this still ends up needing runtime |
49 | | // initialization. |
50 | | #define LAZY_INSTANCE_INITIALIZER {0} |
51 | | |
52 | | namespace base { |
53 | | |
54 | | template <typename Type> |
55 | | struct LazyInstanceTraitsBase { |
56 | 0 | static Type* New(void* instance) { |
57 | 0 | DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (alignof(Type) - 1), 0u); |
58 | 0 | // Use placement new to initialize our instance in our preallocated space. |
59 | 0 | // The parenthesis is very important here to force POD type initialization. |
60 | 0 | return new (instance) Type(); |
61 | 0 | } |
62 | | |
63 | | static void CallDestructor(Type* instance) { |
64 | | // Explicitly call the destructor. |
65 | | instance->~Type(); |
66 | | } |
67 | | }; |
68 | | |
69 | | // We pull out some of the functionality into non-templated functions, so we |
70 | | // can implement the more complicated pieces out of line in the .cc file. |
71 | | namespace internal { |
72 | | |
73 | | // This traits class causes destruction the contained Type at process exit via |
74 | | // AtExitManager. This is probably generally not what you want. Instead, prefer |
75 | | // Leaky below. |
76 | | template <typename Type> |
77 | | struct DestructorAtExitLazyInstanceTraits { |
78 | | static const bool kRegisterOnExit = true; |
79 | | #if DCHECK_IS_ON() |
80 | | static const bool kAllowedToAccessOnNonjoinableThread = false; |
81 | | #endif |
82 | | |
83 | | static Type* New(void* instance) { |
84 | | return LazyInstanceTraitsBase<Type>::New(instance); |
85 | | } |
86 | | |
87 | | static void Delete(Type* instance) { |
88 | | LazyInstanceTraitsBase<Type>::CallDestructor(instance); |
89 | | } |
90 | | }; |
91 | | |
92 | | // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: |
93 | | // base::LazyInstance<T>::Leaky my_leaky_lazy_instance; |
94 | | // instead of: |
95 | | // base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> > |
96 | | // my_leaky_lazy_instance; |
97 | | // (especially when T is MyLongTypeNameImplClientHolderFactory). |
98 | | // Only use this internal::-qualified verbose form to extend this traits class |
99 | | // (depending on its implementation details). |
100 | | template <typename Type> |
101 | | struct LeakyLazyInstanceTraits { |
102 | | static const bool kRegisterOnExit = false; |
103 | | #if DCHECK_IS_ON() |
104 | | static const bool kAllowedToAccessOnNonjoinableThread = true; |
105 | | #endif |
106 | | |
107 | 0 | static Type* New(void* instance) { |
108 | 0 | ANNOTATE_SCOPED_MEMORY_LEAK; |
109 | 0 | return LazyInstanceTraitsBase<Type>::New(instance); |
110 | 0 | } |
111 | 0 | static void Delete(Type* instance) { |
112 | 0 | } |
113 | | }; |
114 | | |
115 | | template <typename Type> |
116 | | struct ErrorMustSelectLazyOrDestructorAtExitForLazyInstance {}; |
117 | | |
118 | | // Our AtomicWord doubles as a spinlock, where a value of |
119 | | // kLazyInstanceStateCreating means the spinlock is being held for creation. |
120 | | constexpr subtle::AtomicWord kLazyInstanceStateCreating = 1; |
121 | | |
122 | | // Check if instance needs to be created. If so return true otherwise |
123 | | // if another thread has beat us, wait for instance to be created and |
124 | | // return false. |
125 | | BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); |
126 | | |
127 | | // After creating an instance, call this to register the dtor to be called |
128 | | // at program exit and to update the atomic state to hold the |new_instance| |
129 | | BASE_EXPORT void CompleteLazyInstance(subtle::AtomicWord* state, |
130 | | subtle::AtomicWord new_instance, |
131 | | void (*destructor)(void*), |
132 | | void* destructor_arg); |
133 | | |
134 | | // If |state| is uninitialized, constructs a value using |creator_func|, stores |
135 | | // it into |state| and registers |destructor| to be called with |destructor_arg| |
136 | | // as argument when the current AtExitManager goes out of scope. Then, returns |
137 | | // the value stored in |state|. It is safe to have concurrent calls to this |
138 | | // function with the same |state|. |
139 | | template <typename CreatorFunc> |
140 | | void* GetOrCreateLazyPointer(subtle::AtomicWord* state, |
141 | | const CreatorFunc& creator_func, |
142 | | void (*destructor)(void*), |
143 | 0 | void* destructor_arg) { |
144 | 0 | // If any bit in the created mask is true, the instance has already been |
145 | 0 | // fully constructed. |
146 | 0 | constexpr subtle::AtomicWord kLazyInstanceCreatedMask = |
147 | 0 | ~internal::kLazyInstanceStateCreating; |
148 | 0 |
|
149 | 0 | // We will hopefully have fast access when the instance is already created. |
150 | 0 | // Since a thread sees |state| == 0 or kLazyInstanceStateCreating at most |
151 | 0 | // once, the load is taken out of NeedsLazyInstance() as a fast-path. The load |
152 | 0 | // has acquire memory ordering as a thread which sees |state| > creating needs |
153 | 0 | // to acquire visibility over the associated data. Pairing Release_Store is in |
154 | 0 | // CompleteLazyInstance(). |
155 | 0 | subtle::AtomicWord value = subtle::Acquire_Load(state); |
156 | 0 | if (!(value & kLazyInstanceCreatedMask) && NeedsLazyInstance(state)) { |
157 | 0 | // Create the instance in the space provided by |private_buf_|. |
158 | 0 | value = reinterpret_cast<subtle::AtomicWord>(creator_func()); |
159 | 0 | CompleteLazyInstance(state, value, destructor, destructor_arg); |
160 | 0 | } |
161 | 0 | return reinterpret_cast<void*>(subtle::NoBarrier_Load(state)); |
162 | 0 | } |
163 | | |
164 | | } // namespace internal |
165 | | |
166 | | template < |
167 | | typename Type, |
168 | | typename Traits = |
169 | | internal::ErrorMustSelectLazyOrDestructorAtExitForLazyInstance<Type>> |
170 | | class LazyInstance { |
171 | | public: |
172 | | // Do not define a destructor, as doing so makes LazyInstance a |
173 | | // non-POD-struct. We don't want that because then a static initializer will |
174 | | // be created to register the (empty) destructor with atexit() under MSVC, for |
175 | | // example. We handle destruction of the contained Type class explicitly via |
176 | | // the OnExit member function, where needed. |
177 | | // ~LazyInstance() {} |
178 | | |
179 | | // Convenience typedef to avoid having to repeat Type for leaky lazy |
180 | | // instances. |
181 | | typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type>> Leaky; |
182 | | typedef LazyInstance<Type, internal::DestructorAtExitLazyInstanceTraits<Type>> |
183 | | DestructorAtExit; |
184 | | |
185 | 0 | Type& Get() { |
186 | 0 | return *Pointer(); |
187 | 0 | } |
188 | | |
189 | 0 | Type* Pointer() { |
190 | | #if DCHECK_IS_ON() |
191 | | // Avoid making TLS lookup on release builds. |
192 | | if (!Traits::kAllowedToAccessOnNonjoinableThread) |
193 | | ThreadRestrictions::AssertSingletonAllowed(); |
194 | | #endif |
195 | | return static_cast<Type*>(internal::GetOrCreateLazyPointer( |
196 | 0 | &private_instance_, |
197 | 0 | [this]() { return Traits::New(private_buf_); }, |
198 | 0 | Traits::kRegisterOnExit ? OnExit : nullptr, this)); |
199 | 0 | } |
200 | | |
201 | | bool operator==(Type* p) { |
202 | | switch (subtle::NoBarrier_Load(&private_instance_)) { |
203 | | case 0: |
204 | | return p == NULL; |
205 | | case internal::kLazyInstanceStateCreating: |
206 | | return static_cast<void*>(p) == private_buf_; |
207 | | default: |
208 | | return p == instance(); |
209 | | } |
210 | | } |
211 | | |
212 | | // MSVC gives a warning that the alignment expands the size of the |
213 | | // LazyInstance struct to make the size a multiple of the alignment. This |
214 | | // is expected in this case. |
215 | | #if defined(OS_WIN) |
216 | | #pragma warning(push) |
217 | | #pragma warning(disable: 4324) |
218 | | #endif |
219 | | |
220 | | // Effectively private: member data is only public to allow the linker to |
221 | | // statically initialize it and to maintain a POD class. DO NOT USE FROM |
222 | | // OUTSIDE THIS CLASS. |
223 | | subtle::AtomicWord private_instance_; |
224 | | |
225 | | // Preallocated space for the Type instance. |
226 | | alignas(Type) char private_buf_[sizeof(Type)]; |
227 | | |
228 | | #if defined(OS_WIN) |
229 | | #pragma warning(pop) |
230 | | #endif |
231 | | |
232 | | private: |
233 | 0 | Type* instance() { |
234 | 0 | return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_)); |
235 | 0 | } |
236 | | |
237 | | // Adapter function for use with AtExit. This should be called single |
238 | | // threaded, so don't synchronize across threads. |
239 | | // Calling OnExit while the instance is in use by other threads is a mistake. |
240 | 0 | static void OnExit(void* lazy_instance) { |
241 | 0 | LazyInstance<Type, Traits>* me = |
242 | 0 | reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); |
243 | 0 | Traits::Delete(me->instance()); |
244 | 0 | subtle::NoBarrier_Store(&me->private_instance_, 0); |
245 | 0 | } |
246 | | }; |
247 | | |
248 | | } // namespace base |
249 | | |
250 | | #endif // BASE_LAZY_INSTANCE_H_ |