blob: 1be34883a77b24563f2e8633a1d9729baa01533f [file] [log] [blame]
dvyukov@google.com6beeb832011-05-17 00:01:54 +09001// Copyright (c) 2011 The Chromium Authors. All rights reserved.
deanm@google.coma6deb002008-09-08 23:11:13 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/lazy_instance.h"
6
7#include "base/at_exit.h"
8#include "base/atomicops.h"
9#include "base/basictypes.h"
brettw@chromium.org61391822011-01-01 05:02:16 +090010#include "base/threading/platform_thread.h"
timurrrr@chromium.orgf39c3ff2010-05-14 17:24:42 +090011#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
deanm@google.coma6deb002008-09-08 23:11:13 +090012
13namespace base {
14
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090015bool LazyInstanceHelper::NeedsInstance() {
deanm@google.coma6deb002008-09-08 23:11:13 +090016 // Try to create the instance, if we're the first, will go from EMPTY
17 // to CREATING, otherwise we've already been beaten here.
dvyukov@google.com6beeb832011-05-17 00:01:54 +090018 // The memory access has no memory ordering as STATE_EMPTY and STATE_CREATING
19 // has no associated data (memory barriers are all about ordering
20 // of memory accesses to *associated* data).
21 if (base::subtle::NoBarrier_CompareAndSwap(
22 &state_, STATE_EMPTY, STATE_CREATING) == STATE_EMPTY)
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090023 // Caller must create instance
24 return true;
dvyukov@google.com6beeb832011-05-17 00:01:54 +090025
26 // It's either in the process of being created, or already created. Spin.
27 // The load has acquire memory ordering as a thread which sees
28 // state_ == STATE_CREATED needs to acquire visibility over
29 // the associated data (buf_). Pairing Release_Store is in
30 // CompleteInstance().
31 while (base::subtle::Acquire_Load(&state_) != STATE_CREATED)
32 PlatformThread::YieldCurrentThread();
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090033
34 // Someone else created the instance.
35 return false;
36}
37
38void LazyInstanceHelper::CompleteInstance(void* instance, void (*dtor)(void*)) {
39 // See the comment to the corresponding HAPPENS_AFTER in Pointer().
40 ANNOTATE_HAPPENS_BEFORE(&state_);
41
42 // Instance is created, go from CREATING to CREATED.
dvyukov@google.com6beeb832011-05-17 00:01:54 +090043 // Releases visibility over buf_ to readers. Pairing Acquire_Load's are in
44 // NeedsInstance() and Pointer().
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090045 base::subtle::Release_Store(&state_, STATE_CREATED);
46
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090047 // Make sure that the lazily instantiated object will get destroyed at exit.
evan@chromium.orga04f70c2010-10-22 05:41:47 +090048 if (dtor)
49 base::AtExitManager::RegisterCallback(dtor, instance);
deanm@google.coma6deb002008-09-08 23:11:13 +090050}
51
deanm@google.coma6deb002008-09-08 23:11:13 +090052} // namespace base
dvyukov@google.com6beeb832011-05-17 00:01:54 +090053
54
55