OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // The LazyInstance<Type, Traits> class manages a single instance of Type, | 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 | 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 | 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 | 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() | 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. | 10 // and Pointer() will always return the same, completely initialized instance. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 // Use placement new to initialize our instance in our preallocated space. | 66 // Use placement new to initialize our instance in our preallocated space. |
67 // The parenthesis is very important here to force POD type initialization. | 67 // The parenthesis is very important here to force POD type initialization. |
68 return new (instance) Type(); | 68 return new (instance) Type(); |
69 } | 69 } |
70 static void Delete(Type* instance) { | 70 static void Delete(Type* instance) { |
71 // Explicitly call the destructor. | 71 // Explicitly call the destructor. |
72 instance->~Type(); | 72 instance->~Type(); |
73 } | 73 } |
74 }; | 74 }; |
75 | 75 |
76 // We pull out some of the functionality into non-templated functions, so we | |
77 // can implement the more complicated pieces out of line in the .cc file. | |
78 namespace internal { | |
79 | |
76 // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: | 80 // Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.: |
77 // base::LazyInstance<T>::Leaky my_leaky_lazy_instance; | 81 // base::LazyInstance<T>::Leaky my_leaky_lazy_instance; |
78 // instead of: | 82 // instead of: |
79 // base::LazyInstance<T, LeakyLazyInstanceTraits<T> > my_leaky_lazy_instance; | 83 // base::LazyInstance<T, LeakyLazyInstanceTraits<T> > my_leaky_lazy_instance; |
wtc
2012/01/24 19:39:53
Nit: In this sample code, LeakyLazyInstanceTraits
Ami GONE FROM CHROMIUM
2012/01/24 20:27:30
Right; done.
| |
80 // (especially when T is MyLongTypeNameImplClientHolderFactory). | 84 // (especially when T is MyLongTypeNameImplClientHolderFactory). |
85 // Only use this internal::-qualified verbose form to extend this traits class | |
86 // (depending on its implementation details). | |
81 template <typename Type> | 87 template <typename Type> |
82 struct LeakyLazyInstanceTraits { | 88 struct LeakyLazyInstanceTraits { |
83 static const bool kRegisterOnExit = false; | 89 static const bool kRegisterOnExit = false; |
84 static const bool kAllowedToAccessOnNonjoinableThread = true; | 90 static const bool kAllowedToAccessOnNonjoinableThread = true; |
85 | 91 |
86 static Type* New(void* instance) { | 92 static Type* New(void* instance) { |
87 return DefaultLazyInstanceTraits<Type>::New(instance); | 93 return DefaultLazyInstanceTraits<Type>::New(instance); |
88 } | 94 } |
89 static void Delete(Type* instance) { | 95 static void Delete(Type* instance) { |
90 } | 96 } |
91 }; | 97 }; |
92 | 98 |
93 // We pull out some of the functionality into non-templated functions, so we | |
94 // can implement the more complicated pieces out of line in the .cc file. | |
95 namespace internal { | |
96 | |
97 // Our AtomicWord doubles as a spinlock, where a value of | 99 // Our AtomicWord doubles as a spinlock, where a value of |
98 // kBeingCreatedMarker means the spinlock is being held for creation. | 100 // kBeingCreatedMarker means the spinlock is being held for creation. |
99 static const subtle::AtomicWord kLazyInstanceStateCreating = 1; | 101 static const subtle::AtomicWord kLazyInstanceStateCreating = 1; |
100 | 102 |
101 // Check if instance needs to be created. If so return true otherwise | 103 // Check if instance needs to be created. If so return true otherwise |
102 // if another thread has beat us, wait for instance to be created and | 104 // if another thread has beat us, wait for instance to be created and |
103 // return false. | 105 // return false. |
104 BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); | 106 BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state); |
105 | 107 |
106 // After creating an instance, call this to register the dtor to be called | 108 // After creating an instance, call this to register the dtor to be called |
(...skipping 10 matching lines...) Expand all Loading... | |
117 public: | 119 public: |
118 // Do not define a destructor, as doing so makes LazyInstance a | 120 // Do not define a destructor, as doing so makes LazyInstance a |
119 // non-POD-struct. We don't want that because then a static initializer will | 121 // non-POD-struct. We don't want that because then a static initializer will |
120 // be created to register the (empty) destructor with atexit() under MSVC, for | 122 // be created to register the (empty) destructor with atexit() under MSVC, for |
121 // example. We handle destruction of the contained Type class explicitly via | 123 // example. We handle destruction of the contained Type class explicitly via |
122 // the OnExit member function, where needed. | 124 // the OnExit member function, where needed. |
123 // ~LazyInstance() {} | 125 // ~LazyInstance() {} |
124 | 126 |
125 // Convenience typedef to avoid having to repeat Type for leaky lazy | 127 // Convenience typedef to avoid having to repeat Type for leaky lazy |
126 // instances. | 128 // instances. |
127 typedef LazyInstance<Type, LeakyLazyInstanceTraits<Type> > Leaky; | 129 typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type> > Leaky; |
128 | 130 |
129 Type& Get() { | 131 Type& Get() { |
130 return *Pointer(); | 132 return *Pointer(); |
131 } | 133 } |
132 | 134 |
133 Type* Pointer() { | 135 Type* Pointer() { |
134 #ifndef NDEBUG | 136 #ifndef NDEBUG |
135 // Avoid making TLS lookup on release builds. | 137 // Avoid making TLS lookup on release builds. |
136 if (!Traits::kAllowedToAccessOnNonjoinableThread) | 138 if (!Traits::kAllowedToAccessOnNonjoinableThread) |
137 ThreadRestrictions::AssertSingletonAllowed(); | 139 ThreadRestrictions::AssertSingletonAllowed(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 LazyInstance<Type, Traits>* me = | 200 LazyInstance<Type, Traits>* me = |
199 reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); | 201 reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); |
200 Traits::Delete(me->instance()); | 202 Traits::Delete(me->instance()); |
201 subtle::Release_Store(&me->private_instance_, 0); | 203 subtle::Release_Store(&me->private_instance_, 0); |
202 } | 204 } |
203 }; | 205 }; |
204 | 206 |
205 } // namespace base | 207 } // namespace base |
206 | 208 |
207 #endif // BASE_LAZY_INSTANCE_H_ | 209 #endif // BASE_LAZY_INSTANCE_H_ |
OLD | NEW |