| 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);
|
| };
|
|
|