OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // The LazyInstance<Type, Traits> class manages a single instance of Type, | 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 | 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 | 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 | 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() | 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. | 10 // and Pointer() will always return the same, completely initialized instance. |
(...skipping 18 matching lines...) Expand all Loading... |
29 // my_instance.Get().SomeMethod(); // MyClass::SomeMethod() | 29 // my_instance.Get().SomeMethod(); // MyClass::SomeMethod() |
30 // | 30 // |
31 // MyClass* ptr = my_instance.Pointer(); | 31 // MyClass* ptr = my_instance.Pointer(); |
32 // ptr->DoDoDo(); // MyClass::DoDoDo | 32 // ptr->DoDoDo(); // MyClass::DoDoDo |
33 // } | 33 // } |
34 | 34 |
35 #ifndef BASE_LAZY_INSTANCE_H_ | 35 #ifndef BASE_LAZY_INSTANCE_H_ |
36 #define BASE_LAZY_INSTANCE_H_ | 36 #define BASE_LAZY_INSTANCE_H_ |
37 #pragma once | 37 #pragma once |
38 | 38 |
| 39 #include <new> // For placement new. |
| 40 |
39 #include "base/atomicops.h" | 41 #include "base/atomicops.h" |
40 #include "base/basictypes.h" | 42 #include "base/basictypes.h" |
41 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 43 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
| 44 #include "base/thread_restrictions.h" |
42 | 45 |
43 namespace base { | 46 namespace base { |
44 | 47 |
45 template <typename Type> | 48 template <typename Type> |
46 struct DefaultLazyInstanceTraits { | 49 struct DefaultLazyInstanceTraits { |
| 50 static const bool kAllowedToAccessOnNonjoinableThread = false; |
| 51 |
47 static Type* New(void* instance) { | 52 static Type* New(void* instance) { |
48 // Use placement new to initialize our instance in our preallocated space. | 53 // Use placement new to initialize our instance in our preallocated space. |
49 // The parenthesis is very important here to force POD type initialization. | 54 // The parenthesis is very important here to force POD type initialization. |
50 return new (instance) Type(); | 55 return new (instance) Type(); |
51 } | 56 } |
52 static void Delete(void* instance) { | 57 static void Delete(void* instance) { |
53 // Explicitly call the destructor. | 58 // Explicitly call the destructor. |
54 reinterpret_cast<Type*>(instance)->~Type(); | 59 reinterpret_cast<Type*>(instance)->~Type(); |
55 } | 60 } |
56 }; | 61 }; |
57 | 62 |
58 template <typename Type> | 63 template <typename Type> |
59 struct LeakyLazyInstanceTraits { | 64 struct LeakyLazyInstanceTraits { |
| 65 static const bool kAllowedToAccessOnNonjoinableThread = true; |
| 66 |
60 static Type* New(void* instance) { | 67 static Type* New(void* instance) { |
61 return DefaultLazyInstanceTraits<Type>::New(instance); | 68 return DefaultLazyInstanceTraits<Type>::New(instance); |
62 } | 69 } |
63 // Rather than define an empty Delete function, we make Delete itself | 70 // Rather than define an empty Delete function, we make Delete itself |
64 // a null pointer. This allows us to completely sidestep registering | 71 // a null pointer. This allows us to completely sidestep registering |
65 // this object with an AtExitManager, which allows you to use | 72 // this object with an AtExitManager, which allows you to use |
66 // LeakyLazyInstanceTraits in contexts where you don't have an | 73 // LeakyLazyInstanceTraits in contexts where you don't have an |
67 // AtExitManager. | 74 // AtExitManager. |
68 static void (*Delete)(void* instance); | 75 static void (*Delete)(void* instance); |
69 }; | 76 }; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 public: | 112 public: |
106 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { } | 113 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { } |
107 // Declaring a destructor (even if it's empty) will cause MSVC to register a | 114 // Declaring a destructor (even if it's empty) will cause MSVC to register a |
108 // static initializer to register the empty destructor with atexit(). | 115 // static initializer to register the empty destructor with atexit(). |
109 | 116 |
110 Type& Get() { | 117 Type& Get() { |
111 return *Pointer(); | 118 return *Pointer(); |
112 } | 119 } |
113 | 120 |
114 Type* Pointer() { | 121 Type* Pointer() { |
| 122 if (!Traits::kAllowedToAccessOnNonjoinableThread) |
| 123 base::ThreadRestrictions::AssertSingletonAllowed(); |
| 124 |
115 // We will hopefully have fast access when the instance is already created. | 125 // We will hopefully have fast access when the instance is already created. |
116 if ((base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) && | 126 if ((base::subtle::NoBarrier_Load(&state_) != STATE_CREATED) && |
117 NeedsInstance()) { | 127 NeedsInstance()) { |
118 // Create the instance in the space provided by |buf_|. | 128 // Create the instance in the space provided by |buf_|. |
119 instance_ = Traits::New(buf_); | 129 instance_ = Traits::New(buf_); |
120 CompleteInstance(instance_, Traits::Delete); | 130 CompleteInstance(instance_, Traits::Delete); |
121 } | 131 } |
122 | 132 |
123 // This annotation helps race detectors recognize correct lock-less | 133 // This annotation helps race detectors recognize correct lock-less |
124 // synchronization between different threads calling Pointer(). | 134 // synchronization between different threads calling Pointer(). |
125 // We suggest dynamic race detection tool that "Traits::New" above | 135 // We suggest dynamic race detection tool that "Traits::New" above |
126 // and CompleteInstance(...) happens before "return instance_" below. | 136 // and CompleteInstance(...) happens before "return instance_" below. |
127 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...). | 137 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...). |
128 ANNOTATE_HAPPENS_AFTER(&state_); | 138 ANNOTATE_HAPPENS_AFTER(&state_); |
129 | |
130 return instance_; | 139 return instance_; |
131 } | 140 } |
132 | 141 |
133 private: | 142 private: |
134 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance. | 143 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance. |
135 Type *instance_; | 144 Type *instance_; |
136 | 145 |
137 DISALLOW_COPY_AND_ASSIGN(LazyInstance); | 146 DISALLOW_COPY_AND_ASSIGN(LazyInstance); |
138 }; | 147 }; |
139 | 148 |
140 } // namespace base | 149 } // namespace base |
141 | 150 |
142 #endif // BASE_LAZY_INSTANCE_H_ | 151 #endif // BASE_LAZY_INSTANCE_H_ |
OLD | NEW |