blob: ac94a009111cf230ef70984add4b22034f53fdac [file] [log] [blame]
[email protected]f53121d2011-03-22 22:11:081// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]30039e62008-09-08 14:11:132// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// The LazyInstance<Type, Traits> class manages a single instance of Type,
6// which will be lazily created on the first time it's accessed. This class is
7// useful for places you would normally use a function-level static, but you
8// need to have guaranteed thread-safety. The Type constructor will only ever
9// be called once, even if two threads are racing to create the object. Get()
10// and Pointer() will always return the same, completely initialized instance.
11// When the instance is constructed it is registered with AtExitManager. The
12// destructor will be called on program exit.
13//
14// LazyInstance is completely thread safe, assuming that you create it safely.
15// The class was designed to be POD initialized, so it shouldn't require a
16// static constructor. It really only makes sense to declare a LazyInstance as
17// a global variable using the base::LinkerInitialized constructor.
18//
19// LazyInstance is similar to Singleton, except it does not have the singleton
20// property. You can have multiple LazyInstance's of the same type, and each
21// will manage a unique instance. It also preallocates the space for Type, as
22// to avoid allocating the Type instance on the heap. This may help with the
23// performance of creating the instance, and reducing heap fragmentation. This
24// requires that Type be a complete type so we can determine the size.
25//
26// Example usage:
[email protected]de1f44a2009-01-13 12:34:5327// static LazyInstance<MyClass> my_instance(base::LINKER_INITIALIZED);
[email protected]30039e62008-09-08 14:11:1328// void SomeMethod() {
29// my_instance.Get().SomeMethod(); // MyClass::SomeMethod()
[email protected]52a261f2009-03-03 15:01:1230//
[email protected]30039e62008-09-08 14:11:1331// MyClass* ptr = my_instance.Pointer();
32// ptr->DoDoDo(); // MyClass::DoDoDo
33// }
34
35#ifndef BASE_LAZY_INSTANCE_H_
36#define BASE_LAZY_INSTANCE_H_
[email protected]32b76ef2010-07-26 23:08:2437#pragma once
[email protected]30039e62008-09-08 14:11:1338
[email protected]359d2bf2010-11-19 20:34:1839#include <new> // For placement new.
40
[email protected]30039e62008-09-08 14:11:1341#include "base/atomicops.h"
[email protected]0bea7252011-08-05 15:34:0042#include "base/base_export.h"
[email protected]30039e62008-09-08 14:11:1343#include "base/basictypes.h"
[email protected]e4a638f762011-10-21 19:46:0044#include "base/logging.h"
[email protected]ee857512010-05-14 08:24:4245#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]34b99632011-01-01 01:01:0646#include "base/threading/thread_restrictions.h"
[email protected]30039e62008-09-08 14:11:1347
48namespace base {
49
50template <typename Type>
51struct DefaultLazyInstanceTraits {
[email protected]113eee02011-10-25 19:04:4852 static const bool kRegisterOnExit = true;
[email protected]359d2bf2010-11-19 20:34:1853 static const bool kAllowedToAccessOnNonjoinableThread = false;
54
[email protected]c1aeaac2010-03-12 15:28:4855 static Type* New(void* instance) {
[email protected]e4a638f762011-10-21 19:46:0056 DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) % sizeof(instance), 0u)
57 << ": Bad boy, the buffer passed to placement new is not aligned!\n"
58 "This may break some stuff like SSE-based optimizations assuming the "
59 "<Type> objects are word aligned.";
[email protected]30039e62008-09-08 14:11:1360 // Use placement new to initialize our instance in our preallocated space.
61 // The parenthesis is very important here to force POD type initialization.
[email protected]c1aeaac2010-03-12 15:28:4862 return new (instance) Type();
[email protected]30039e62008-09-08 14:11:1363 }
[email protected]113eee02011-10-25 19:04:4864 static void Delete(Type* instance) {
[email protected]30039e62008-09-08 14:11:1365 // Explicitly call the destructor.
[email protected]113eee02011-10-25 19:04:4866 instance->~Type();
[email protected]30039e62008-09-08 14:11:1367 }
68};
69
[email protected]dcc69332010-10-21 20:41:4770template <typename Type>
71struct LeakyLazyInstanceTraits {
[email protected]113eee02011-10-25 19:04:4872 static const bool kRegisterOnExit = false;
[email protected]359d2bf2010-11-19 20:34:1873 static const bool kAllowedToAccessOnNonjoinableThread = true;
74
[email protected]dcc69332010-10-21 20:41:4775 static Type* New(void* instance) {
76 return DefaultLazyInstanceTraits<Type>::New(instance);
77 }
[email protected]113eee02011-10-25 19:04:4878 static void Delete(Type* instance) {
79 }
[email protected]dcc69332010-10-21 20:41:4780};
81
[email protected]30039e62008-09-08 14:11:1382// We pull out some of the functionality into a non-templated base, so that we
83// can implement the more complicated pieces out of line in the .cc file.
[email protected]0bea7252011-08-05 15:34:0084class BASE_EXPORT LazyInstanceHelper {
[email protected]30039e62008-09-08 14:11:1385 protected:
86 enum {
87 STATE_EMPTY = 0,
88 STATE_CREATING = 1,
89 STATE_CREATED = 2
90 };
91
[email protected]6ebed4ca2011-02-25 02:18:1392 explicit LazyInstanceHelper(LinkerInitialized /*unused*/) {/* state_ is 0 */}
[email protected]1b651d52011-05-16 15:01:5493
[email protected]62ea4512008-09-08 15:20:5794 // Declaring a destructor (even if it's empty) will cause MSVC to register a
95 // static initializer to register the empty destructor with atexit().
[email protected]30039e62008-09-08 14:11:1396
[email protected]1b651d52011-05-16 15:01:5497 // A destructor is intentionally not defined. If we were to say
98 // ~LazyInstanceHelper() { }
99 // Even though it's empty, a destructor will still be generated.
100 // In order for the constructor to be called for static variables,
101 // it will be registered as a callback at runtime with AtExit().
102 // We don't want this, so we don't declare a destructor at all,
103 // effectively keeping the type POD (at least in terms of
104 // initialization and destruction).
105
[email protected]c1aeaac2010-03-12 15:28:48106 // Check if instance needs to be created. If so return true otherwise
107 // if another thread has beat us, wait for instance to be created and
108 // return false.
109 bool NeedsInstance();
110
111 // After creating an instance, call this to register the dtor to be called
112 // at program exit and to update the state to STATE_CREATED.
113 void CompleteInstance(void* instance, void (*dtor)(void*));
[email protected]30039e62008-09-08 14:11:13114
115 base::subtle::Atomic32 state_;
[email protected]3d5314782008-09-08 14:47:24116
117 private:
118 DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper);
[email protected]30039e62008-09-08 14:11:13119};
120
121template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
122class LazyInstance : public LazyInstanceHelper {
123 public:
124 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
[email protected]1b651d52011-05-16 15:01:54125
[email protected]62ea4512008-09-08 15:20:57126 // Declaring a destructor (even if it's empty) will cause MSVC to register a
127 // static initializer to register the empty destructor with atexit().
[email protected]1b651d52011-05-16 15:01:54128 // Refer to the destructor-related comment in LazyInstanceHelper.
129 // ~LazyInstance() {}
[email protected]30039e62008-09-08 14:11:13130
131 Type& Get() {
132 return *Pointer();
133 }
134
135 Type* Pointer() {
[email protected]3c7a7f32011-11-04 17:29:10136#ifndef NDEBUG
137 // Avoid making TLS lookup on release builds.
[email protected]359d2bf2010-11-19 20:34:18138 if (!Traits::kAllowedToAccessOnNonjoinableThread)
139 base::ThreadRestrictions::AssertSingletonAllowed();
[email protected]3c7a7f32011-11-04 17:29:10140#endif
[email protected]359d2bf2010-11-19 20:34:18141
[email protected]30039e62008-09-08 14:11:13142 // We will hopefully have fast access when the instance is already created.
[email protected]1b651d52011-05-16 15:01:54143 // Since a thread sees state_ != STATE_CREATED at most once,
144 // the load is taken out of NeedsInstance() as a fast-path.
145 // The load has acquire memory ordering as a thread which sees
146 // state_ == STATE_CREATED needs to acquire visibility over
147 // the associated data (buf_). Pairing Release_Store is in
148 // CompleteInstance().
149 if ((base::subtle::Acquire_Load(&state_) != STATE_CREATED) &&
[email protected]c1aeaac2010-03-12 15:28:48150 NeedsInstance()) {
151 // Create the instance in the space provided by |buf_|.
152 instance_ = Traits::New(buf_);
[email protected]113eee02011-10-25 19:04:48153 CompleteInstance(this, Traits::kRegisterOnExit ? OnExit : NULL);
[email protected]c1aeaac2010-03-12 15:28:48154 }
[email protected]30039e62008-09-08 14:11:13155
[email protected]001b6942009-06-26 11:28:03156 // This annotation helps race detectors recognize correct lock-less
157 // synchronization between different threads calling Pointer().
[email protected]c1aeaac2010-03-12 15:28:48158 // We suggest dynamic race detection tool that "Traits::New" above
159 // and CompleteInstance(...) happens before "return instance_" below.
160 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...).
[email protected]001b6942009-06-26 11:28:03161 ANNOTATE_HAPPENS_AFTER(&state_);
[email protected]c1aeaac2010-03-12 15:28:48162 return instance_;
[email protected]30039e62008-09-08 14:11:13163 }
164
[email protected]332710b2011-02-22 19:21:59165 bool operator==(Type* p) {
166 switch (base::subtle::NoBarrier_Load(&state_)) {
167 case STATE_EMPTY:
168 return p == NULL;
169 case STATE_CREATING:
170 return static_cast<int8*>(static_cast<void*>(p)) == buf_;
171 case STATE_CREATED:
172 return p == instance_;
173 default:
174 return false;
175 }
176 }
177
[email protected]30039e62008-09-08 14:11:13178 private:
[email protected]625332e02010-12-14 07:48:49179 // Adapter function for use with AtExit. This should be called single
[email protected]113eee02011-10-25 19:04:48180 // threaded, so don't synchronize across threads.
[email protected]625332e02010-12-14 07:48:49181 // Calling OnExit while the instance is in use by other threads is a mistake.
182 static void OnExit(void* lazy_instance) {
183 LazyInstance<Type, Traits>* me =
184 reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
185 Traits::Delete(me->instance_);
186 me->instance_ = NULL;
187 base::subtle::Release_Store(&me->state_, STATE_EMPTY);
188 }
189
[email protected]c1aeaac2010-03-12 15:28:48190 Type *instance_;
[email protected]e4a638f762011-10-21 19:46:00191 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
[email protected]30039e62008-09-08 14:11:13192
193 DISALLOW_COPY_AND_ASSIGN(LazyInstance);
194};
195
196} // namespace base
197
198#endif // BASE_LAZY_INSTANCE_H_