blob: f8d59873f297484a120ebf927fcd2bfeb48bdb79 [file] [log] [blame]
[email protected]30039e62008-09-08 14:11:131// Copyright (c) 2008 The Chromium Authors. All rights reserved.
2// 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"
42#include "base/basictypes.h"
[email protected]ee857512010-05-14 08:24:4243#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]359d2bf2010-11-19 20:34:1844#include "base/thread_restrictions.h"
[email protected]30039e62008-09-08 14:11:1345
46namespace base {
47
48template <typename Type>
49struct DefaultLazyInstanceTraits {
[email protected]359d2bf2010-11-19 20:34:1850 static const bool kAllowedToAccessOnNonjoinableThread = false;
51
[email protected]c1aeaac2010-03-12 15:28:4852 static Type* New(void* instance) {
[email protected]30039e62008-09-08 14:11:1353 // Use placement new to initialize our instance in our preallocated space.
54 // The parenthesis is very important here to force POD type initialization.
[email protected]c1aeaac2010-03-12 15:28:4855 return new (instance) Type();
[email protected]30039e62008-09-08 14:11:1356 }
57 static void Delete(void* instance) {
58 // Explicitly call the destructor.
59 reinterpret_cast<Type*>(instance)->~Type();
60 }
61};
62
[email protected]dcc69332010-10-21 20:41:4763template <typename Type>
64struct LeakyLazyInstanceTraits {
[email protected]359d2bf2010-11-19 20:34:1865 static const bool kAllowedToAccessOnNonjoinableThread = true;
66
[email protected]dcc69332010-10-21 20:41:4767 static Type* New(void* instance) {
68 return DefaultLazyInstanceTraits<Type>::New(instance);
69 }
70 // Rather than define an empty Delete function, we make Delete itself
71 // a null pointer. This allows us to completely sidestep registering
72 // this object with an AtExitManager, which allows you to use
73 // LeakyLazyInstanceTraits in contexts where you don't have an
74 // AtExitManager.
75 static void (*Delete)(void* instance);
76};
77
78template <typename Type>
79void (*LeakyLazyInstanceTraits<Type>::Delete)(void* instance) = NULL;
80
[email protected]30039e62008-09-08 14:11:1381// We pull out some of the functionality into a non-templated base, so that we
82// can implement the more complicated pieces out of line in the .cc file.
83class LazyInstanceHelper {
84 protected:
85 enum {
86 STATE_EMPTY = 0,
87 STATE_CREATING = 1,
88 STATE_CREATED = 2
89 };
90
91 explicit LazyInstanceHelper(LinkerInitialized x) { /* state_ is 0 */ }
[email protected]62ea4512008-09-08 15:20:5792 // Declaring a destructor (even if it's empty) will cause MSVC to register a
93 // static initializer to register the empty destructor with atexit().
[email protected]30039e62008-09-08 14:11:1394
[email protected]c1aeaac2010-03-12 15:28:4895 // Check if instance needs to be created. If so return true otherwise
96 // if another thread has beat us, wait for instance to be created and
97 // return false.
98 bool NeedsInstance();
99
100 // After creating an instance, call this to register the dtor to be called
101 // at program exit and to update the state to STATE_CREATED.
102 void CompleteInstance(void* instance, void (*dtor)(void*));
[email protected]30039e62008-09-08 14:11:13103
104 base::subtle::Atomic32 state_;
[email protected]3d5314782008-09-08 14:47:24105
106 private:
107 DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper);
[email protected]30039e62008-09-08 14:11:13108};
109
110template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
111class LazyInstance : public LazyInstanceHelper {
112 public:
113 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
[email protected]62ea4512008-09-08 15:20:57114 // Declaring a destructor (even if it's empty) will cause MSVC to register a
115 // static initializer to register the empty destructor with atexit().
[email protected]30039e62008-09-08 14:11:13116
117 Type& Get() {
118 return *Pointer();
119 }
120
121 Type* Pointer() {
[email protected]359d2bf2010-11-19 20:34:18122 if (!Traits::kAllowedToAccessOnNonjoinableThread)
123 base::ThreadRestrictions::AssertSingletonAllowed();
124
[email protected]30039e62008-09-08 14:11:13125 // We will hopefully have fast access when the instance is already created.
[email protected]c1aeaac2010-03-12 15:28:48126 if ((base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) &&
127 NeedsInstance()) {
128 // Create the instance in the space provided by |buf_|.
129 instance_ = Traits::New(buf_);
130 CompleteInstance(instance_, Traits::Delete);
131 }
[email protected]30039e62008-09-08 14:11:13132
[email protected]001b6942009-06-26 11:28:03133 // This annotation helps race detectors recognize correct lock-less
134 // synchronization between different threads calling Pointer().
[email protected]c1aeaac2010-03-12 15:28:48135 // We suggest dynamic race detection tool that "Traits::New" above
136 // and CompleteInstance(...) happens before "return instance_" below.
137 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...).
[email protected]001b6942009-06-26 11:28:03138 ANNOTATE_HAPPENS_AFTER(&state_);
[email protected]c1aeaac2010-03-12 15:28:48139 return instance_;
[email protected]30039e62008-09-08 14:11:13140 }
141
142 private:
143 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
[email protected]c1aeaac2010-03-12 15:28:48144 Type *instance_;
[email protected]30039e62008-09-08 14:11:13145
146 DISALLOW_COPY_AND_ASSIGN(LazyInstance);
147};
148
149} // namespace base
150
151#endif // BASE_LAZY_INSTANCE_H_