diff options
author | craig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 15:28:48 +0000 |
---|---|---|
committer | craig.schlenter@chromium.org <craig.schlenter@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 15:28:48 +0000 |
commit | c1aeaac2015e93e1168453d4de29619c43fda669 (patch) | |
tree | 062ebdcfdcca6b6f8c781ede55b5dc7d97e8f142 /base/lazy_instance.cc | |
parent | dc99ca7f7328d14d43af2fd5b8cde944c6a08054 (diff) | |
download | chromium_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.cc')
-rw-r--r-- | base/lazy_instance.cc | 43 |
1 files changed, 23 insertions, 20 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 |