summaryrefslogtreecommitdiffstats
path: root/base/lazy_instance.h
diff options
context:
space:
mode:
authorcraig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 15:28:48 +0000
committercraig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 15:28:48 +0000
commitc1aeaac2015e93e1168453d4de29619c43fda669 (patch)
tree062ebdcfdcca6b6f8c781ede55b5dc7d97e8f142 /base/lazy_instance.h
parentdc99ca7f7328d14d43af2fd5b8cde944c6a08054 (diff)
downloadchromium_src-c1aeaac2015e93e1168453d4de29619c43fda669.zip
chromium_src-c1aeaac2015e93e1168453d4de29619c43fda669.tar.gz
chromium_src-c1aeaac2015e93e1168453d4de29619c43fda669.tar.bz2
Avoid a strict aliasing issue in LazyInstance.
The key change here is to use the return value from placement new rather than casting buf_. Avoiding the cast avoids the strict aliasing issue. BUG=28749 Review URL: http://codereview.chromium.org/548011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41434 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/lazy_instance.h')
-rw-r--r--base/lazy_instance.h36
1 files changed, 21 insertions, 15 deletions
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);
};