Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: base/lazy_instance.h

Issue 5242002: Reland 66791 (change was innocent)... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | base/message_loop_proxy_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | base/message_loop_proxy_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698