Index: base/lazy_instance.h |
diff --git a/base/lazy_instance.h b/base/lazy_instance.h |
index ac94a009111cf230ef70984add4b22034f53fdac..e8a4a8a043feb69981fa5b64d2558908e11ef480 100644 |
--- a/base/lazy_instance.h |
+++ b/base/lazy_instance.h |
@@ -14,7 +14,7 @@ |
// LazyInstance is completely thread safe, assuming that you create it safely. |
// The class was designed to be POD initialized, so it shouldn't require a |
// static constructor. It really only makes sense to declare a LazyInstance as |
-// a global variable using the base::LinkerInitialized constructor. |
+// a global variable using the LAZY_INSTANCE_INITIALIZER initializer. |
// |
// LazyInstance is similar to Singleton, except it does not have the singleton |
// property. You can have multiple LazyInstance's of the same type, and each |
@@ -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 = LAZY_INSTANCE_INITIALIZER; |
// void SomeMethod() { |
// my_instance.Get().SomeMethod(); // MyClass::SomeMethod() |
// |
@@ -45,6 +45,12 @@ |
#include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
#include "base/threading/thread_restrictions.h" |
+// LazyInstance uses its own struct initializer-list style static |
+// initialization, as base's LINKER_INITIALIZED requires a constructor and on |
+// some compilers (notably gcc 4.4) this still ends up needing runtime |
+// initialization. |
+#define LAZY_INSTANCE_INITIALIZER {0} |
+ |
namespace base { |
template <typename Type> |
@@ -79,53 +85,36 @@ struct LeakyLazyInstanceTraits { |
} |
}; |
-// We pull out some of the functionality into a non-templated base, so that we |
+// We pull out some of the functionality into non-templated functions, so 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 |
- }; |
- |
- explicit LazyInstanceHelper(LinkerInitialized /*unused*/) {/* state_ is 0 */} |
- |
- // 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(); |
- |
- // 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*)); |
- |
- base::subtle::Atomic32 state_; |
+namespace internal { |
- private: |
- DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper); |
-}; |
+// 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; |
+ |
+// 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(subtle::AtomicWord* state); |
+ |
+// 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(subtle::AtomicWord* state, |
+ subtle::AtomicWord new_instance, |
+ void* lazy_instance, |
+ void (*dtor)(void*)); |
+ |
+} // namespace internal |
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. |
+ // Do not define a destructor, as doing so makes LazyInstance a |
+ // non-POD-struct. We don't want that because then a static initializer will |
+ // be created to register the (empty) destructor with atexit() under MSVC, for |
+ // example. We handle destruction of the contained Type class explicitly via |
+ // the OnExit member function, where needed. |
// ~LazyInstance() {} |
Type& Get() { |
@@ -136,61 +125,70 @@ class LazyInstance : public LazyInstanceHelper { |
#ifndef NDEBUG |
// Avoid making TLS lookup on release builds. |
if (!Traits::kAllowedToAccessOnNonjoinableThread) |
- base::ThreadRestrictions::AssertSingletonAllowed(); |
+ ThreadRestrictions::AssertSingletonAllowed(); |
#endif |
+ // If any bit in the created mask is true, the instance has already been |
+ // fully constructed. |
+ static const subtle::AtomicWord kLazyInstanceCreatedMask = |
+ ~internal::kLazyInstanceStateCreating; |
// We will hopefully have fast access when the instance is already created. |
- // Since a thread sees state_ != STATE_CREATED at most once, |
- // the load is taken out of NeedsInstance() as a fast-path. |
+ // Since a thread sees private_instance_ == 0 or kLazyInstanceStateCreating |
+ // at most once, 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 |
- // 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); |
+ // private_instance_ > creating needs to acquire visibility over |
+ // the associated data (private_buf_). Pairing Release_Store is in |
+ // CompleteLazyInstance(). |
+ subtle::AtomicWord value = subtle::Acquire_Load(&private_instance_); |
+ if (!(value & kLazyInstanceCreatedMask) && |
+ internal::NeedsLazyInstance(&private_instance_)) { |
+ // Create the instance in the space provided by |private_buf_|. |
+ value = reinterpret_cast<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. |
- // See the corresponding HAPPENS_BEFORE in CompleteInstance(...). |
- ANNOTATE_HAPPENS_AFTER(&state_); |
- return instance_; |
+ // and CompleteLazyInstance(...) happens before "return instance()" below. |
+ // See the corresponding HAPPENS_BEFORE in CompleteLazyInstance(...). |
+ ANNOTATE_HAPPENS_AFTER(&private_instance_); |
+ return instance(); |
} |
bool operator==(Type* p) { |
- switch (base::subtle::NoBarrier_Load(&state_)) { |
- case STATE_EMPTY: |
+ switch (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 |
+ // statically initialize it. DO NOT USE FROM OUTSIDE THIS CLASS. |
+ |
+ // Note this must use AtomicWord, not Atomic32, to ensure correct alignment |
+ // of |private_buf_| on 64 bit architectures. (This member must be first to |
+ // allow the syntax used in LAZY_INSTANCE_INITIALIZER to work correctly.) |
+ subtle::AtomicWord private_instance_; |
+ 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()); |
+ 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 |