Chromium Code Reviews| Index: base/lazy_instance.h |
| diff --git a/base/lazy_instance.h b/base/lazy_instance.h |
| index ac94a009111cf230ef70984add4b22034f53fdac..7812cf99b61e7e08dcdbee7850b08af2337a2dbe 100644 |
| --- a/base/lazy_instance.h |
| +++ b/base/lazy_instance.h |
| @@ -24,7 +24,7 @@ |
| // requires that Type be a complete type so we can determine the size. |
| // |
| // Example usage: |
| -// static LazyInstance<MyClass> my_instance(base::LINKER_INITIALIZED); |
| +// static LazyInstance<MyClass> my_instance = LINKER_ZERO_INITIALIZED; |
|
Nico
2011/11/11 20:21:56
Is this needed? Aren't statics implicitly zero ini
joth
2011/11/14 16:58:23
Just needed as a double check to prove to the call
|
| // void SomeMethod() { |
| // my_instance.Get().SomeMethod(); // MyClass::SomeMethod() |
| // |
| @@ -79,53 +79,44 @@ struct LeakyLazyInstanceTraits { |
| } |
| }; |
| -// We pull out some of the functionality into a non-templated base, so that we |
| -// can implement the more complicated pieces out of line in the .cc file. |
| -class BASE_EXPORT LazyInstanceHelper { |
| - protected: |
| - enum { |
| - STATE_EMPTY = 0, |
| - STATE_CREATING = 1, |
| - STATE_CREATED = 2 |
| - }; |
| +// We pull out some of the functionality into a non-templated functions, so we |
| +// we can implement the more complicated pieces out of line in the .cc file. |
| +namespace internal { |
| - explicit LazyInstanceHelper(LinkerInitialized /*unused*/) {/* state_ is 0 */} |
| +// Our AtomicWord doubles as a spinlock, where a value of |
| +// kBeingCreatedMarker means the spinlock is being held for creation. |
| +static const subtle::AtomicWord kLazyInstanceStateCreating = 1; |
| - // Declaring a destructor (even if it's empty) will cause MSVC to register a |
| - // static initializer to register the empty destructor with atexit(). |
| +// Declaring a destructor (even if it's empty) will cause MSVC to register a |
| +// static initializer to register the empty destructor with atexit(). |
| - // A destructor is intentionally not defined. If we were to say |
| - // ~LazyInstanceHelper() { } |
| - // Even though it's empty, a destructor will still be generated. |
| - // In order for the constructor to be called for static variables, |
| - // it will be registered as a callback at runtime with AtExit(). |
| - // We don't want this, so we don't declare a destructor at all, |
| - // effectively keeping the type POD (at least in terms of |
| - // initialization and destruction). |
| - |
| - // Check if instance needs to be created. If so return true otherwise |
| - // if another thread has beat us, wait for instance to be created and |
| - // return false. |
| - bool NeedsInstance(); |
| +// Check if instance needs to be created. If so return true otherwise |
| +// if another thread has beat us, wait for instance to be created and |
| +// return false. |
| +BASE_EXPORT bool NeedsLazyInstance(base::subtle::AtomicWord* state); |
| - // After creating an instance, call this to register the dtor to be called |
| - // at program exit and to update the state to STATE_CREATED. |
| - void CompleteInstance(void* instance, void (*dtor)(void*)); |
| +// After creating an instance, call this to register the dtor to be called |
| +// at program exit and to update the atomic state to hold the |new_instance| |
| +BASE_EXPORT void CompleteLazyInstance(base::subtle::AtomicWord* state, |
| + base::subtle::AtomicWord new_instance, |
| + void* lazy_instance, |
| + void (*dtor)(void*)); |
| - base::subtle::Atomic32 state_; |
| +} // namespace internal |
| - private: |
| - DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper); |
| -}; |
| +#define LINKER_ZERO_INITIALIZED {0} |
| template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > |
| -class LazyInstance : public LazyInstanceHelper { |
| +class LazyInstance { |
| public: |
| - explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { } |
| - |
| // Declaring a destructor (even if it's empty) will cause MSVC to register a |
| // static initializer to register the empty destructor with atexit(). |
| - // Refer to the destructor-related comment in LazyInstanceHelper. |
| + // Even though it's empty, a destructor will still be generated. |
| + // In order for the constructor to be called for static variables, |
| + // it will be registered as a callback at runtime with AtExit(). |
| + // We don't want this, so we don't declare a destructor at all, |
| + // effectively keeping the type POD (at least in terms of |
| + // initialization and destruction). |
| // ~LazyInstance() {} |
| Type& Get() { |
| @@ -140,57 +131,62 @@ class LazyInstance : public LazyInstanceHelper { |
| #endif |
| // We will hopefully have fast access when the instance is already created. |
| - // Since a thread sees state_ != STATE_CREATED at most once, |
| + // Since a thread sees private_instance_ == 0 or Creating at most once, |
|
willchan no longer on Chromium
2011/11/11 22:18:21
You mean kLazyInstanceStateCreating instead of jus
joth
2011/11/14 16:58:23
Done.
|
| // the load is taken out of NeedsInstance() as a fast-path. |
| // The load has acquire memory ordering as a thread which sees |
| - // state_ == STATE_CREATED needs to acquire visibility over |
| - // the associated data (buf_). Pairing Release_Store is in |
| + // private_instance_ > creating needs to acquire visibility over |
| + // the associated data (private_buf_). Pairing Release_Store is in |
| // CompleteInstance(). |
| - if ((base::subtle::Acquire_Load(&state_) != STATE_CREATED) && |
| - NeedsInstance()) { |
| - // Create the instance in the space provided by |buf_|. |
| - instance_ = Traits::New(buf_); |
| - CompleteInstance(this, Traits::kRegisterOnExit ? OnExit : NULL); |
| + base::subtle::AtomicWord value = |
|
willchan no longer on Chromium
2011/11/11 22:18:21
No need to use base:: from within the base namespa
joth
2011/11/14 16:58:23
Done. here & many other places in .h and .cc
|
| + base::subtle::Acquire_Load(&private_instance_); |
| + if ((value == 0 || value == internal::kLazyInstanceStateCreating) && |
|
willchan no longer on Chromium
2011/11/11 22:18:21
I'm not sure I understand why we changed away from
joth
2011/11/14 16:58:23
Yep memory reduction plus consistency with Singlet
|
| + internal::NeedsLazyInstance(&private_instance_)) { |
| + // Create the instance in the space provided by |private_buf_|. |
| + value = reinterpret_cast<base::subtle::AtomicWord>( |
| + Traits::New(private_buf_)); |
| + internal::CompleteLazyInstance(&private_instance_, value, this, |
| + Traits::kRegisterOnExit ? OnExit : NULL); |
| } |
| // This annotation helps race detectors recognize correct lock-less |
| // synchronization between different threads calling Pointer(). |
| // We suggest dynamic race detection tool that "Traits::New" above |
| - // and CompleteInstance(...) happens before "return instance_" below. |
| + // and CompleteInstance(...) happens before "return instance()" below. |
| // See the corresponding HAPPENS_BEFORE in CompleteInstance(...). |
| - ANNOTATE_HAPPENS_AFTER(&state_); |
| - return instance_; |
| + ANNOTATE_HAPPENS_AFTER(&private_instance_); |
| + return instance(); |
| } |
| bool operator==(Type* p) { |
| - switch (base::subtle::NoBarrier_Load(&state_)) { |
| - case STATE_EMPTY: |
| + switch (base::subtle::NoBarrier_Load(&private_instance_)) { |
| + case 0: |
| return p == NULL; |
| - case STATE_CREATING: |
| - return static_cast<int8*>(static_cast<void*>(p)) == buf_; |
| - case STATE_CREATED: |
| - return p == instance_; |
| + case internal::kLazyInstanceStateCreating: |
| + return static_cast<int8*>(static_cast<void*>(p)) == private_buf_; |
| default: |
| - return false; |
| + return p == instance(); |
| } |
| } |
| + // Effectively private: member data is only public to allow the linker to |
|
Nico
2011/11/11 20:21:56
Sentence cut off
joth
2011/11/11 21:15:36
Done.
|
| + // Note this must use AtomicWord, not Atomic32, to ensure correct alignment of |
| + // |private_buf_| on 64 bit arcchitectures. |
|
Nico
2011/11/11 20:21:56
spello arcchitectures
joth
2011/11/11 21:15:36
Done.
|
| + base::subtle::AtomicWord private_instance_; |
| + // statically initialize it. DO NOT USE FROM OUTSIDE THIS CLASS. |
| + int8 private_buf_[sizeof(Type)]; // Preallocated space for the Type instance. |
| + |
| private: |
| + Type* instance() { return reinterpret_cast<Type*>(private_instance_); } |
| + |
| // Adapter function for use with AtExit. This should be called single |
| // threaded, so don't synchronize across threads. |
| // Calling OnExit while the instance is in use by other threads is a mistake. |
| static void OnExit(void* lazy_instance) { |
| LazyInstance<Type, Traits>* me = |
| reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance); |
| - Traits::Delete(me->instance_); |
| - me->instance_ = NULL; |
| - base::subtle::Release_Store(&me->state_, STATE_EMPTY); |
| + Traits::Delete(me->instance()); |
| + base::subtle::Release_Store(&me->private_instance_, 0); |
| } |
| - |
| - Type *instance_; |
| - int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance. |
| - |
| - DISALLOW_COPY_AND_ASSIGN(LazyInstance); |
| }; |
| } // namespace base |