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

Side by Side Diff: third_party/libphonenumber/cpp/src/base/lazy_instance.h

Issue 6803005: Autofill phone number enhancements and integration of Phone Number Util Library: part 1 (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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
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:
27 // static LazyInstance<MyClass> my_instance(base::LINKER_INITIALIZED);
28 // void SomeMethod() {
29 // my_instance.Get().SomeMethod(); // MyClass::SomeMethod()
30 //
31 // MyClass* ptr = my_instance.Pointer();
32 // ptr->DoDoDo(); // MyClass::DoDoDo
33 // }
34
35 #ifndef BASE_LAZY_INSTANCE_H_
36 #define BASE_LAZY_INSTANCE_H_
37 #pragma once
38
39 #include <new> // For placement new.
40
41 #include "base/atomicops.h"
42 #include "base/basictypes.h"
43 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
44 #include "base/threading/thread_restrictions.h"
45
46 namespace base {
47
48 template <typename Type>
49 struct DefaultLazyInstanceTraits {
50 static const bool kAllowedToAccessOnNonjoinableThread = false;
51
52 static Type* New(void* instance) {
53 // Use placement new to initialize our instance in our preallocated space.
54 // The parenthesis is very important here to force POD type initialization.
55 return new (instance) Type();
56 }
57 static void Delete(void* instance) {
58 // Explicitly call the destructor.
59 reinterpret_cast<Type*>(instance)->~Type();
60 }
61 };
62
63 template <typename Type>
64 struct LeakyLazyInstanceTraits {
65 static const bool kAllowedToAccessOnNonjoinableThread = true;
66
67 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
78 template <typename Type>
79 void (*LeakyLazyInstanceTraits<Type>::Delete)(void* instance) = NULL;
80
81 // 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.
83 class LazyInstanceHelper {
84 protected:
85 enum {
86 STATE_EMPTY = 0,
87 STATE_CREATING = 1,
88 STATE_CREATED = 2
89 };
90
91 explicit LazyInstanceHelper(LinkerInitialized /*unused*/) {/* state_ is 0 */}
92 // Declaring a destructor (even if it's empty) will cause MSVC to register a
93 // static initializer to register the empty destructor with atexit().
94
95 // 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*));
103
104 base::subtle::Atomic32 state_;
105
106 private:
107 DISALLOW_COPY_AND_ASSIGN(LazyInstanceHelper);
108 };
109
110 template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
111 class LazyInstance : public LazyInstanceHelper {
112 public:
113 explicit LazyInstance(LinkerInitialized x) : LazyInstanceHelper(x) { }
114 // Declaring a destructor (even if it's empty) will cause MSVC to register a
115 // static initializer to register the empty destructor with atexit().
116
117 Type& Get() {
118 return *Pointer();
119 }
120
121 Type* Pointer() {
122 if (!Traits::kAllowedToAccessOnNonjoinableThread)
123 base::ThreadRestrictions::AssertSingletonAllowed();
124
125 // We will hopefully have fast access when the instance is already created.
126 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 // Traits::Delete will be null for LeakyLazyInstanceTraits
131 void (*dtor)(void*) = Traits::Delete;
132 CompleteInstance(this, (dtor == NULL) ? NULL : OnExit);
133 }
134
135 // This annotation helps race detectors recognize correct lock-less
136 // synchronization between different threads calling Pointer().
137 // We suggest dynamic race detection tool that "Traits::New" above
138 // and CompleteInstance(...) happens before "return instance_" below.
139 // See the corresponding HAPPENS_BEFORE in CompleteInstance(...).
140 ANNOTATE_HAPPENS_AFTER(&state_);
141 return instance_;
142 }
143
144 bool operator==(Type* p) {
145 switch (base::subtle::NoBarrier_Load(&state_)) {
146 case STATE_EMPTY:
147 return p == NULL;
148 case STATE_CREATING:
149 return static_cast<int8*>(static_cast<void*>(p)) == buf_;
150 case STATE_CREATED:
151 return p == instance_;
152 default:
153 return false;
154 }
155 }
156
157 private:
158 // Adapter function for use with AtExit. This should be called single
159 // threaded, so don't use atomic operations.
160 // Calling OnExit while the instance is in use by other threads is a mistake.
161 static void OnExit(void* lazy_instance) {
162 LazyInstance<Type, Traits>* me =
163 reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
164 Traits::Delete(me->instance_);
165 me->instance_ = NULL;
166 base::subtle::Release_Store(&me->state_, STATE_EMPTY);
167 }
168
169 int8 buf_[sizeof(Type)]; // Preallocate the space for the Type instance.
170 Type *instance_;
171
172 DISALLOW_COPY_AND_ASSIGN(LazyInstance);
173 };
174
175 } // namespace base
176
177 #endif // BASE_LAZY_INSTANCE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698