summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/lazy_instance.cc43
-rw-r--r--base/lazy_instance.h36
2 files changed, 44 insertions, 35 deletions
diff --git a/base/lazy_instance.cc b/base/lazy_instance.cc
index 9923253..565ad1f 100644
--- a/base/lazy_instance.cc
+++ b/base/lazy_instance.cc
@@ -12,35 +12,38 @@
namespace base {
-void LazyInstanceHelper::EnsureInstance(void* instance,
- void (*ctor)(void*),
- void (*dtor)(void*)) {
+bool LazyInstanceHelper::NeedsInstance() {
// 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) {
- // Created the instance in the space provided by |instance|.
- ctor(instance);
-
- // 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(&LazyInstanceHelper::ResetState,
- this);
-
- // Make sure that the lazily instantiated object will get destroyed at exit.
- base::AtExitManager::RegisterCallback(dtor, instance);
+ // Caller must create instance
+ return true;
} else {
// It's either in the process of being created, or already created. Spin.
while (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED)
PlatformThread::YieldCurrentThread();
}
+
+ // Someone else created the instance.
+ return false;
+}
+
+void LazyInstanceHelper::CompleteInstance(void* instance, void (*dtor)(void*)) {
+ // 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(&LazyInstanceHelper::ResetState,
+ this);
+
+ // Make sure that the lazily instantiated object will get destroyed at exit.
+ base::AtExitManager::RegisterCallback(dtor, instance);
}
// static
diff --git a/base/lazy_instance.h b/base/lazy_instance.h
index d7754a7..c6c170c 100644
--- a/base/lazy_instance.h
+++ b/base/lazy_instance.h
@@ -43,10 +43,10 @@ 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.
@@ -68,10 +68,14 @@ class LazyInstanceHelper {
// 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*));
+ // 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_;
@@ -95,25 +99,27 @@ 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);
+ if ((base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) &&
+ NeedsInstance()) {
+ // Create the instance in the space provided by |buf_|.
+ instance_ = Traits::New(buf_);
+ CompleteInstance(instance_, Traits::Delete);
+ }
// 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(...).
+ // 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;
+ return instance_;
}
private:
int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
+ Type *instance_;
DISALLOW_COPY_AND_ASSIGN(LazyInstance);
};