/src/brpc/src/butil/lazy_instance.h
Line | Count | Source |
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> my_instance = LAZY_INSTANCE_INITIALIZER; |
28 | | // void SomeMethod() { |
29 | | // my_instance.Get().SomeMethod(); // MyClass::SomeMethod() |
30 | | // |
31 | | // MyClass* ptr = my_instance.Pointer(); |
32 | | // ptr->DoDoDo(); // MyClass::DoDoDo |
33 | | // } |
34 | | |
35 | | #ifndef BUTIL_LAZY_INSTANCE_H_ |
36 | | #define BUTIL_LAZY_INSTANCE_H_ |
37 | | |
38 | | #include <new> // For placement new. |
39 | | |
40 | | #include "butil/atomicops.h" |
41 | | #include "butil/base_export.h" |
42 | | #include "butil/debug/leak_annotations.h" |
43 | | #include "butil/logging.h" |
44 | | #include "butil/memory/aligned_memory.h" |
45 | | #include "butil/third_party/dynamic_annotations/dynamic_annotations.h" |
46 | | #include "butil/threading/thread_restrictions.h" |
47 | | |
48 | | // LazyInstance uses its own struct initializer-list style static |
49 | | // initialization, as base's LINKER_INITIALIZED requires a constructor and on |
50 | | // some compilers (notably gcc 4.4) this still ends up needing runtime |
51 | | // initialization. |
52 | | #define LAZY_INSTANCE_INITIALIZER { 0, {{0}} } |
53 | | |
54 | | namespace butil { |
55 | | |
56 | | template <typename Type> |
57 | | struct DefaultLazyInstanceTraits { |
58 | | static const bool kRegisterOnExit; |
59 | | #ifndef NDEBUG |
60 | | static const bool kAllowedToAccessOnNonjoinableThread; |
61 | | #endif |
62 | | |
63 | 0 | static Type* New(void* instance) { |
64 | 0 | DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (ALIGNOF(Type) - 1), 0u) |
65 | 0 | << ": Bad boy, the buffer passed to placement new is not aligned!\n" |
66 | 0 | "This may break some stuff like SSE-based optimizations assuming the " |
67 | 0 | "<Type> objects are word aligned."; |
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 | 0 | return new (instance) Type(); |
71 | 0 | } Unexecuted instantiation: butil::DefaultLazyInstanceTraits<butil::UnixEpochSingleton>::New(void*) Unexecuted instantiation: butil::DefaultLazyInstanceTraits<butil::Lock>::New(void*) |
72 | | static void Delete(Type* instance) { |
73 | | // Explicitly call the destructor. |
74 | | instance->~Type(); |
75 | | } |
76 | | }; |
77 | | |
78 | | // NOTE(gejun): BullseyeCoverage Compile C++ 8.4.4 complains about `undefined |
79 | | // reference' on in-place assignments to static constants. |
80 | | template <typename Type> |
81 | | const bool DefaultLazyInstanceTraits<Type>::kRegisterOnExit = true; |
82 | | #ifndef NDEBUG |
83 | | template <typename Type> |
84 | | const bool DefaultLazyInstanceTraits<Type>::kAllowedToAccessOnNonjoinableThread = false; |
85 | | #endif |
86 | | |
87 | | // We pull out some of the functionality into non-templated functions, so we |
88 | | // can implement the more complicated pieces out of line in the .cc file. |
89 | | namespace internal { |
90 | | |
91 | | // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: |
92 | | // butil::LazyInstance<T>::Leaky my_leaky_lazy_instance; |
93 | | // instead of: |
94 | | // butil::LazyInstance<T, butil::internal::LeakyLazyInstanceTraits<T> > |
95 | | // my_leaky_lazy_instance; |
96 | | // (especially when T is MyLongTypeNameImplClientHolderFactory). |
97 | | // Only use this internal::-qualified verbose form to extend this traits class |
98 | | // (depending on its implementation details). |
99 | | template <typename Type> |
100 | | struct LeakyLazyInstanceTraits { |
101 | | static const bool kRegisterOnExit; |
102 | | #ifndef NDEBUG |
103 | | static const bool kAllowedToAccessOnNonjoinableThread; |
104 | | #endif |
105 | | |
106 | 0 | static Type* New(void* instance) { |
107 | | // Instruct LeakSanitizer to ignore the designated memory leak. |
108 | 0 | ANNOTATE_SCOPED_MEMORY_LEAK; |
109 | 0 | return DefaultLazyInstanceTraits<Type>::New(instance); |
110 | 0 | } Unexecuted instantiation: butil::internal::LeakyLazyInstanceTraits<butil::UnixEpochSingleton>::New(void*) Unexecuted instantiation: butil::internal::LeakyLazyInstanceTraits<butil::Lock>::New(void*) |
111 | 0 | static void Delete(Type* instance) { |
112 | 0 | } Unexecuted instantiation: butil::internal::LeakyLazyInstanceTraits<butil::UnixEpochSingleton>::Delete(butil::UnixEpochSingleton*) Unexecuted instantiation: butil::internal::LeakyLazyInstanceTraits<butil::Lock>::Delete(butil::Lock*) |
113 | | }; |
114 | | |
115 | | template <typename Type> |
116 | | const bool LeakyLazyInstanceTraits<Type>::kRegisterOnExit = false; |
117 | | #ifndef NDEBUG |
118 | | template <typename Type> |
119 | | const bool LeakyLazyInstanceTraits<Type>::kAllowedToAccessOnNonjoinableThread = true; |
120 | | #endif |
121 | | |
122 | | // Our AtomicWord doubles as a spinlock, where a value of |
123 | | // kBeingCreatedMarker means the spinlock is being held for creation. |
124 | | static const subtle::AtomicWord kLazyInstanceStateCreating = 1; |
125 | | |
126 | | // Check if instance needs to be created. If so return true otherwise |
127 | | // if another thread has beat us, wait for instance to be created and |
128 | | // return false. |
129 | | BUTIL_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); |
130 | | |
131 | | // After creating an instance, call this to register the dtor to be called |
132 | | // at program exit and to update the atomic state to hold the |new_instance| |
133 | | BUTIL_EXPORT void CompleteLazyInstance(subtle::AtomicWord* state, |
134 | | subtle::AtomicWord new_instance, |
135 | | void* lazy_instance, |
136 | | void (*dtor)(void*)); |
137 | | |
138 | | } // namespace internal |
139 | | |
140 | | template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > |
141 | | class LazyInstance { |
142 | | public: |
143 | | // Do not define a destructor, as doing so makes LazyInstance a |
144 | | // non-POD-struct. We don't want that because then a static initializer will |
145 | | // be created to register the (empty) destructor with atexit() under MSVC, for |
146 | | // example. We handle destruction of the contained Type class explicitly via |
147 | | // the OnExit member function, where needed. |
148 | | // ~LazyInstance() {} |
149 | | |
150 | | // Convenience typedef to avoid having to repeat Type for leaky lazy |
151 | | // instances. |
152 | | typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type> > Leaky; |
153 | | |
154 | 0 | Type& Get() { |
155 | 0 | return *Pointer(); |
156 | 0 | } |
157 | | |
158 | 0 | Type* Pointer() { |
159 | | #ifndef NDEBUG |
160 | | // Avoid making TLS lookup on release builds. |
161 | | if (!Traits::kAllowedToAccessOnNonjoinableThread) |
162 | | ThreadRestrictions::AssertSingletonAllowed(); |
163 | | #endif |
164 | | // If any bit in the created mask is true, the instance has already been |
165 | | // fully constructed. |
166 | 0 | static const subtle::AtomicWord kLazyInstanceCreatedMask = |
167 | 0 | ~internal::kLazyInstanceStateCreating; |
168 | | |
169 | | // We will hopefully have fast access when the instance is already created. |
170 | | // Since a thread sees private_instance_ == 0 or kLazyInstanceStateCreating |
171 | | // at most once, the load is taken out of NeedsInstance() as a fast-path. |
172 | | // The load has acquire memory ordering as a thread which sees |
173 | | // private_instance_ > creating needs to acquire visibility over |
174 | | // the associated data (private_buf_). Pairing Release_Store is in |
175 | | // CompleteLazyInstance(). |
176 | 0 | subtle::AtomicWord value = subtle::Acquire_Load(&private_instance_); |
177 | 0 | if (!(value & kLazyInstanceCreatedMask) && |
178 | 0 | internal::NeedsLazyInstance(&private_instance_)) { |
179 | | // Create the instance in the space provided by |private_buf_|. |
180 | 0 | value = reinterpret_cast<subtle::AtomicWord>( |
181 | 0 | Traits::New(private_buf_.void_data())); |
182 | 0 | internal::CompleteLazyInstance(&private_instance_, value, this, |
183 | 0 | Traits::kRegisterOnExit ? OnExit : NULL); |
184 | 0 | } |
185 | | |
186 | | // This annotation helps race detectors recognize correct lock-less |
187 | | // synchronization between different threads calling Pointer(). |
188 | | // We suggest dynamic race detection tool that "Traits::New" above |
189 | | // and CompleteLazyInstance(...) happens before "return instance()" below. |
190 | | // See the corresponding HAPPENS_BEFORE in CompleteLazyInstance(...). |
191 | 0 | ANNOTATE_HAPPENS_AFTER(&private_instance_); |
192 | 0 | return instance(); |
193 | 0 | } Unexecuted instantiation: butil::LazyInstance<butil::UnixEpochSingleton, butil::internal::LeakyLazyInstanceTraits<butil::UnixEpochSingleton> >::Pointer() Unexecuted instantiation: butil::LazyInstance<butil::Lock, butil::internal::LeakyLazyInstanceTraits<butil::Lock> >::Pointer() |
194 | | |
195 | | bool operator==(Type* p) { |
196 | | switch (subtle::NoBarrier_Load(&private_instance_)) { |
197 | | case 0: |
198 | | return p == NULL; |
199 | | case internal::kLazyInstanceStateCreating: |
200 | | return static_cast<void*>(p) == private_buf_.void_data(); |
201 | | default: |
202 | | return p == instance(); |
203 | | } |
204 | | } |
205 | | |
206 | | // Effectively private: member data is only public to allow the linker to |
207 | | // statically initialize it and to maintain a POD class. DO NOT USE FROM |
208 | | // OUTSIDE THIS CLASS. |
209 | | |
210 | | subtle::AtomicWord private_instance_; |
211 | | // Preallocated space for the Type instance. |
212 | | butil::AlignedMemory<sizeof(Type), ALIGNOF(Type)> private_buf_; |
213 | | |
214 | | private: |
215 | 0 | Type* instance() { |
216 | 0 | return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_)); |
217 | 0 | } Unexecuted instantiation: butil::LazyInstance<butil::UnixEpochSingleton, butil::internal::LeakyLazyInstanceTraits<butil::UnixEpochSingleton> >::instance() Unexecuted instantiation: butil::LazyInstance<butil::Lock, butil::internal::LeakyLazyInstanceTraits<butil::Lock> >::instance() |
218 | | |
219 | | // Adapter function for use with AtExit. This should be called single |
220 | | // threaded, so don't synchronize across threads. |
221 | | // Calling OnExit while the instance is in use by other threads is a mistake. |
222 | 0 | static void OnExit(void* lazy_instance) { |
223 | 0 | LazyInstance<Type, Traits>* me = |
224 | 0 | reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); |
225 | 0 | Traits::Delete(me->instance()); |
226 | 0 | subtle::NoBarrier_Store(&me->private_instance_, 0); |
227 | 0 | } Unexecuted instantiation: butil::LazyInstance<butil::UnixEpochSingleton, butil::internal::LeakyLazyInstanceTraits<butil::UnixEpochSingleton> >::OnExit(void*) Unexecuted instantiation: butil::LazyInstance<butil::Lock, butil::internal::LeakyLazyInstanceTraits<butil::Lock> >::OnExit(void*) |
228 | | }; |
229 | | |
230 | | } // namespace butil |
231 | | |
232 | | #endif // BUTIL_LAZY_INSTANCE_H_ |