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