blob: 57f8aeb57ddb677a2614d7c16638a532308649ec [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
39#include "base/atomicops.h"
40#include "base/basictypes.h"
[email protected]ee857512010-05-14 08:24:4241#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]30039e62008-09-08 14:11:1342
43namespace base {
44
45template <typename Type>
46struct DefaultLazyInstanceTraits {
[email protected]c1aeaac2010-03-12 15:28:4847 static Type* New(void* instance) {
[email protected]30039e62008-09-08 14:11:1348 // Use placement new to initialize our instance in our preallocated space.
49 // The parenthesis is very important here to force POD type initialization.
[email protected]c1aeaac2010-03-12 15:28:4850 return new (instance) Type();
[email protected]30039e62008-09-08 14:11:1351 }
52 static void Delete(void* instance) {
53 // Explicitly call the destructor.
54 reinterpret_cast<Type*>(instance)->~Type();
55 }
56};
57
58// We pull out some of the functionality into a non-templated base, so that we
59// can implement the more complicated pieces out of line in the .cc file.
60class LazyInstanceHelper {
61 protected:
62 enum {
63 STATE_EMPTY = 0,
64 STATE_CREATING = 1,
65 STATE_CREATED = 2
66 };
67
68 explicit LazyInstanceHelper(LinkerInitialized x) { /* state_ is 0 */ }
[email protected]62ea4512008-09-08 15:20:5769 // Declaring a destructor (even if it's empty) will cause MSVC to register a
70 // static initializer to register the empty destructor with atexit().
[email protected]30039e62008-09-08 14:11:1371
[email protected]c1aeaac2010-03-12 15:28:4872 // Check if instance needs to be created. If so return true otherwise
73 // if another thread has beat us, wait for instance to be created and
74 // return false.
75 bool NeedsInstance();
76
77 // After creating an instance, call this to register the dtor to be called
78 // at program exit and to update the state to STATE_CREATED.
79 void CompleteInstance(void* instance, void (*dtor)(void*));
[email protected]30039e62008-09-08 14:11:1380
81 base::subtle::Atomic32 state_;
[email protected]3d5314782008-09-08 14:47:2482
83 private:
[email protected]4ea927b2009-11-19 09:11:3984 // Resets state of |helper| to STATE_EMPTY so that it can be reused.
85 // Not thread safe.
86 static void ResetState(void* helper);
87
[email protected]3d5314782008-09-08 14:47:2488 DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper);
[email protected]30039e62008-09-08 14:11:1389};
90
91template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
92class LazyInstance : public LazyInstanceHelper {
93 public:
94 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
[email protected]62ea4512008-09-08 15:20:5795 // Declaring a destructor (even if it's empty) will cause MSVC to register a
96 // static initializer to register the empty destructor with atexit().
[email protected]30039e62008-09-08 14:11:1397
98 Type& Get() {
99 return *Pointer();
100 }
101
102 Type* Pointer() {
[email protected]30039e62008-09-08 14:11:13103 // We will hopefully have fast access when the instance is already created.
[email protected]c1aeaac2010-03-12 15:28:48104 if ((base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) &&
105 NeedsInstance()) {
106 // Create the instance in the space provided by |buf_|.
107 instance_ = Traits::New(buf_);
108 CompleteInstance(instance_, Traits::Delete);
109 }
[email protected]30039e62008-09-08 14:11:13110
[email protected]001b6942009-06-26 11:28:03111 // This annotation helps race detectors recognize correct lock-less
112 // synchronization between different threads calling Pointer().
[email protected]c1aeaac2010-03-12 15:28:48113 // We suggest dynamic race detection tool that "Traits::New" above
114 // and CompleteInstance(...) happens before "return instance_" below.
115 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...).
[email protected]001b6942009-06-26 11:28:03116 ANNOTATE_HAPPENS_AFTER(&state_);
117
[email protected]c1aeaac2010-03-12 15:28:48118 return instance_;
[email protected]30039e62008-09-08 14:11:13119 }
120
121 private:
122 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
[email protected]c1aeaac2010-03-12 15:28:48123 Type *instance_;
[email protected]30039e62008-09-08 14:11:13124
125 DISALLOW_COPY_AND_ASSIGN(LazyInstance);
126};
127
128} // namespace base
129
130#endif // BASE_LAZY_INSTANCE_H_