blob: 49c7b8c51c332f6046c969781e165adb7f38cc61 [file] [log] [blame]
rvargas@google.com7a976cf2011-03-23 07:11:08 +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// 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:
deanm@chromium.orgfff03ae2009-01-13 21:34:53 +090027// static LazyInstance<MyClass> my_instance(base::LINKER_INITIALIZED);
deanm@google.coma6deb002008-09-08 23:11:13 +090028// void SomeMethod() {
29// my_instance.Get().SomeMethod(); // MyClass::SomeMethod()
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +090030//
deanm@google.coma6deb002008-09-08 23:11:13 +090031// MyClass* ptr = my_instance.Pointer();
32// ptr->DoDoDo(); // MyClass::DoDoDo
33// }
34
35#ifndef BASE_LAZY_INSTANCE_H_
36#define BASE_LAZY_INSTANCE_H_
thakis@chromium.org01d14522010-07-27 08:08:24 +090037#pragma once
deanm@google.coma6deb002008-09-08 23:11:13 +090038
willchan@chromium.org25726ef2010-11-20 05:34:18 +090039#include <new> // For placement new.
40
deanm@google.coma6deb002008-09-08 23:11:13 +090041#include "base/atomicops.h"
rvargas@google.com7a976cf2011-03-23 07:11:08 +090042#include "base/base_api.h"
deanm@google.coma6deb002008-09-08 23:11:13 +090043#include "base/basictypes.h"
timurrrr@chromium.orgf39c3ff2010-05-14 17:24:42 +090044#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
brettw@chromium.org5b5f5e02011-01-01 10:01:06 +090045#include "base/threading/thread_restrictions.h"
deanm@google.coma6deb002008-09-08 23:11:13 +090046
47namespace base {
48
49template <typename Type>
50struct DefaultLazyInstanceTraits {
willchan@chromium.org25726ef2010-11-20 05:34:18 +090051 static const bool kAllowedToAccessOnNonjoinableThread = false;
52
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090053 static Type* New(void* instance) {
deanm@google.coma6deb002008-09-08 23:11:13 +090054 // Use placement new to initialize our instance in our preallocated space.
55 // The parenthesis is very important here to force POD type initialization.
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +090056 return new (instance) Type();
deanm@google.coma6deb002008-09-08 23:11:13 +090057 }
58 static void Delete(void* instance) {
59 // Explicitly call the destructor.
60 reinterpret_cast<Type*>(instance)->~Type();
61 }
62};
63
evan@chromium.orga04f70c2010-10-22 05:41:47 +090064template <typename Type>
65struct LeakyLazyInstanceTraits {
willchan@chromium.org25726ef2010-11-20 05:34:18 +090066 static const bool kAllowedToAccessOnNonjoinableThread = true;
67
evan@chromium.orga04f70c2010-10-22 05:41:47 +090068 static Type* New(void* instance) {
69 return DefaultLazyInstanceTraits<Type>::New(instance);
70 }
71 // Rather than define an empty Delete function, we make Delete itself
72 // a null pointer. This allows us to completely sidestep registering
73 // this object with an AtExitManager, which allows you to use
74 // LeakyLazyInstanceTraits in contexts where you don't have an
75 // AtExitManager.
76 static void (*Delete)(void* instance);
77};
78
79template <typename Type>
80void (*LeakyLazyInstanceTraits<Type>::Delete)(void* instance) = NULL;
81
deanm@google.coma6deb002008-09-08 23:11:13 +090082// 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.
rvargas@google.com7a976cf2011-03-23 07:11:08 +090084class BASE_API LazyInstanceHelper {
deanm@google.coma6deb002008-09-08 23:11:13 +090085 protected:
86 enum {
87 STATE_EMPTY = 0,
88 STATE_CREATING = 1,
89 STATE_CREATED = 2
90 };
91
joi@chromium.org5444bec2011-02-25 11:18:13 +090092 explicit LazyInstanceHelper(LinkerInitialized /*unused*/) {/* state_ is 0 */}
dvyukov@google.com6beeb832011-05-17 00:01:54 +090093
deanm@google.coma178da02008-09-09 00:20:57 +090094 // Declaring a destructor (even if it's empty) will cause MSVC to register a
95 // static initializer to register the empty destructor with atexit().
deanm@google.coma6deb002008-09-08 23:11:13 +090096
dvyukov@google.com6beeb832011-05-17 00:01:54 +090097 // 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
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900106 // 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*));
deanm@google.coma6deb002008-09-08 23:11:13 +0900114
115 base::subtle::Atomic32 state_;
deanm@google.com0f945d82008-09-08 23:47:24 +0900116
117 private:
118 DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper);
deanm@google.coma6deb002008-09-08 23:11:13 +0900119};
120
121template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
122class LazyInstance : public LazyInstanceHelper {
123 public:
124 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
dvyukov@google.com6beeb832011-05-17 00:01:54 +0900125
deanm@google.coma178da02008-09-09 00:20:57 +0900126 // Declaring a destructor (even if it's empty) will cause MSVC to register a
127 // static initializer to register the empty destructor with atexit().
dvyukov@google.com6beeb832011-05-17 00:01:54 +0900128 // Refer to the destructor-related comment in LazyInstanceHelper.
129 // ~LazyInstance() {}
deanm@google.coma6deb002008-09-08 23:11:13 +0900130
131 Type& Get() {
132 return *Pointer();
133 }
134
135 Type* Pointer() {
willchan@chromium.org25726ef2010-11-20 05:34:18 +0900136 if (!Traits::kAllowedToAccessOnNonjoinableThread)
137 base::ThreadRestrictions::AssertSingletonAllowed();
138
deanm@google.coma6deb002008-09-08 23:11:13 +0900139 // We will hopefully have fast access when the instance is already created.
dvyukov@google.com6beeb832011-05-17 00:01:54 +0900140 // Since a thread sees state_ != STATE_CREATED at most once,
141 // the load is taken out of NeedsInstance() as a fast-path.
142 // The load has acquire memory ordering as a thread which sees
143 // state_ == STATE_CREATED needs to acquire visibility over
144 // the associated data (buf_). Pairing Release_Store is in
145 // CompleteInstance().
146 if ((base::subtle::Acquire_Load(&state_) != STATE_CREATED) &&
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900147 NeedsInstance()) {
148 // Create the instance in the space provided by |buf_|.
149 instance_ = Traits::New(buf_);
dilmah@chromium.org19b68692011-02-23 04:21:59 +0900150 // Traits::Delete will be null for LeakyLazyInstanceTraits
satish@chromium.orgc607bcd2010-12-14 17:16:28 +0900151 void (*dtor)(void*) = Traits::Delete;
152 CompleteInstance(this, (dtor == NULL) ? NULL : OnExit);
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900153 }
deanm@google.coma6deb002008-09-08 23:11:13 +0900154
deanm@chromium.org7c73faa2009-06-26 20:28:03 +0900155 // This annotation helps race detectors recognize correct lock-less
156 // synchronization between different threads calling Pointer().
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900157 // We suggest dynamic race detection tool that "Traits::New" above
158 // and CompleteInstance(...) happens before "return instance_" below.
159 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...).
deanm@chromium.org7c73faa2009-06-26 20:28:03 +0900160 ANNOTATE_HAPPENS_AFTER(&state_);
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900161 return instance_;
deanm@google.coma6deb002008-09-08 23:11:13 +0900162 }
163
dilmah@chromium.org19b68692011-02-23 04:21:59 +0900164 bool operator==(Type* p) {
165 switch (base::subtle::NoBarrier_Load(&state_)) {
166 case STATE_EMPTY:
167 return p == NULL;
168 case STATE_CREATING:
169 return static_cast<int8*>(static_cast<void*>(p)) == buf_;
170 case STATE_CREATED:
171 return p == instance_;
172 default:
173 return false;
174 }
175 }
176
deanm@google.coma6deb002008-09-08 23:11:13 +0900177 private:
satish@chromium.org2940ad12010-12-14 16:48:49 +0900178 // Adapter function for use with AtExit. This should be called single
179 // threaded, so don't use atomic operations.
180 // Calling OnExit while the instance is in use by other threads is a mistake.
181 static void OnExit(void* lazy_instance) {
182 LazyInstance<Type, Traits>* me =
183 reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
184 Traits::Delete(me->instance_);
185 me->instance_ = NULL;
186 base::subtle::Release_Store(&me->state_, STATE_EMPTY);
187 }
188
deanm@google.coma6deb002008-09-08 23:11:13 +0900189 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
craig.schlenter@chromium.org0cf58332010-03-13 00:28:48 +0900190 Type *instance_;
deanm@google.coma6deb002008-09-08 23:11:13 +0900191
192 DISALLOW_COPY_AND_ASSIGN(LazyInstance);
193};
194
195} // namespace base
196
197#endif // BASE_LAZY_INSTANCE_H_