| 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
|
|
|