Index: base/lazy_instance.h |
diff --git a/base/lazy_instance.h b/base/lazy_instance.h |
index d7754a78a8c30c52d646fa199f9e1f45ac464c44..75a44ea358223fdc30dcf0c6cd0f1be3645a442e 100644 |
--- a/base/lazy_instance.h |
+++ b/base/lazy_instance.h |
@@ -35,18 +35,20 @@ |
#ifndef BASE_LAZY_INSTANCE_H_ |
#define BASE_LAZY_INSTANCE_H_ |
+#include "base/at_exit.h" |
#include "base/atomicops.h" |
#include "base/basictypes.h" |
#include "base/dynamic_annotations.h" |
+#include "base/platform_thread.h" |
namespace base { |
template <typename Type> |
struct DefaultLazyInstanceTraits { |
- static void New(void* instance) { |
+ static Type* New(void* instance) { |
// Use placement new to initialize our instance in our preallocated space. |
// The parenthesis is very important here to force POD type initialization. |
- new (instance) Type(); |
+ return new (instance) Type(); |
} |
static void Delete(void* instance) { |
// Explicitly call the destructor. |
@@ -54,39 +56,10 @@ struct DefaultLazyInstanceTraits { |
} |
}; |
-// 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 LazyInstanceHelper { |
- protected: |
- enum { |
- STATE_EMPTY = 0, |
- STATE_CREATING = 1, |
- STATE_CREATED = 2 |
- }; |
- |
- explicit LazyInstanceHelper(LinkerInitialized x) { /* 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(). |
- |
- // Make sure that instance is created, creating or waiting for it to be |
- // created if neccessary. Constructs with |ctor| in the space provided by |
- // |instance| and registers dtor for destruction at program exit. |
- void EnsureInstance(void* instance, void (*ctor)(void*), void (*dtor)(void*)); |
- |
- base::subtle::Atomic32 state_; |
- |
- private: |
- // Resets state of |helper| to STATE_EMPTY so that it can be reused. |
- // Not thread safe. |
- static void ResetState(void* helper); |
- |
- DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper); |
-}; |
- |
template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> > |
-class LazyInstance : public LazyInstanceHelper { |
+class LazyInstance { |
public: |
- explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { } |
+ explicit LazyInstance(LinkerInitialized x) { } |
// Declaring a destructor (even if it's empty) will cause MSVC to register a |
// static initializer to register the empty destructor with atexit(). |
@@ -95,25 +68,68 @@ class LazyInstance : public LazyInstanceHelper { |
} |
Type* Pointer() { |
- Type* instance = reinterpret_cast<Type*>(&buf_); |
- |
// We will hopefully have fast access when the instance is already created. |
if (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) |
- EnsureInstance(instance, Traits::New, Traits::Delete); |
+ EnsureInstance(); |
// This annotation helps race detectors recognize correct lock-less |
// synchronization between different threads calling Pointer(). |
// We suggest dynamic race detection tool that |
- // "ctor(instance)" in EnsureInstance(...) happens before |
- // "return instance" in Pointer(). |
- // See the corresponding HAPPENS_BEFORE in EnsureInstance(...). |
+ // "Traits::New(buf_)" in EnsureInstance() happens before |
+ // "return instance_" in Pointer(). |
+ // See the corresponding HAPPENS_BEFORE in EnsureInstance(). |
ANNOTATE_HAPPENS_AFTER(&state_); |
- return instance; |
+ return instance_; |
} |
private: |
+ enum { |
+ STATE_EMPTY = 0, |
+ STATE_CREATING = 1, |
+ STATE_CREATED = 2 |
+ }; |
+ |
+ // Make sure that instance is created, creating or waiting for it to be |
+ // created if neccessary. Constructs with Traits::New in the space provided |
+ // by buf_ and registers Traits::Delete for destruction at program exit. |
+ void EnsureInstance() { |
+ // Try to create the instance, if we're the first, will go from EMPTY |
+ // to CREATING, otherwise we've already been beaten here. |
+ if (base::subtle::Acquire_CompareAndSwap( |
+ &state_, STATE_EMPTY, STATE_CREATING) == STATE_EMPTY) { |
+ // Create the instance in the space provided by |buf_|. |
+ instance_ = Traits::New(buf_); |
+ |
+ // See the comment to the corresponding HAPPENS_AFTER in Pointer(). |
+ ANNOTATE_HAPPENS_BEFORE(&state_); |
+ |
+ // Instance is created, go from CREATING to CREATED. |
+ base::subtle::Release_Store(&state_, STATE_CREATED); |
+ |
+ // Allow reusing the LazyInstance (reset it to the initial state). This |
+ // makes possible calling all AtExit callbacks between tests. Assumes that |
+ // no other threads execute when AtExit callbacks are processed. |
+ base::AtExitManager::RegisterCallback(&ResetState, this); |
+ |
+ // Make sure that the lazily instantiated object will get destroyed at exit. |
+ base::AtExitManager::RegisterCallback(Traits::Delete, instance_); |
+ } else { |
+ // It's either in the process of being created, or already created. Spin. |
+ while (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) |
+ PlatformThread::YieldCurrentThread(); |
+ } |
+ } |
+ |
+ // Resets state of |lazyinstance| to STATE_EMPTY so that it can be reused. |
+ // Not thread safe. |
+ static void ResetState(void* lazyinstance) { |
+ reinterpret_cast<LazyInstance*>(lazyinstance)->state_ = STATE_EMPTY; |
+ } |
+ |
+ base::subtle::Atomic32 state_; |
int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance. |
+ Type* instance_; |
DISALLOW_COPY_AND_ASSIGN(LazyInstance); |
}; |