13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lazy_instance.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/at_exit.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/atomicops.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool LazyInstanceHelper::NeedsInstance() {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Try to create the instance, if we're the first, will go from EMPTY
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to CREATING, otherwise we've already been beaten here.
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (base::subtle::Acquire_CompareAndSwap(
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &state_, STATE_EMPTY, STATE_CREATING) == STATE_EMPTY) {
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Caller must create instance
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // It's either in the process of being created, or already created.  Spin.
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (base::subtle::NoBarrier_Load(&state_) != STATE_CREATED)
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThread::YieldCurrentThread();
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Someone else created the instance.
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid LazyInstanceHelper::CompleteInstance(void* instance, void (*dtor)(void*)) {
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See the comment to the corresponding HAPPENS_AFTER in Pointer().
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ANNOTATE_HAPPENS_BEFORE(&state_);
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Instance is created, go from CREATING to CREATED.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::subtle::Release_Store(&state_, STATE_CREATED);
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure that the lazily instantiated object will get destroyed at exit.
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (dtor)
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    base::AtExitManager::RegisterCallback(dtor, instance);
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
45