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

Side by Side Diff: base/singleton.h

Issue 5682008: Make members of Singleton<T> private and only visible to the singleton type. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 10 years 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
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #ifndef BASE_SINGLETON_H_ 5 #ifndef BASE_SINGLETON_H_
6 #define BASE_SINGLETON_H_ 6 #define BASE_SINGLETON_H_
7 #pragma once 7 #pragma once
8 8
9 #include "base/at_exit.h" 9 #include "base/at_exit.h"
10 #include "base/atomicops.h" 10 #include "base/atomicops.h"
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 107
108 // Signal the object was already deleted, so it is not revived. 108 // Signal the object was already deleted, so it is not revived.
109 static base::subtle::Atomic32 dead_; 109 static base::subtle::Atomic32 dead_;
110 }; 110 };
111 111
112 template <typename Type> intptr_t 112 template <typename Type> intptr_t
113 StaticMemorySingletonTraits<Type>::buffer_[kBufferSize]; 113 StaticMemorySingletonTraits<Type>::buffer_[kBufferSize];
114 template <typename Type> base::subtle::Atomic32 114 template <typename Type> base::subtle::Atomic32
115 StaticMemorySingletonTraits<Type>::dead_ = 0; 115 StaticMemorySingletonTraits<Type>::dead_ = 0;
116 116
117 // This is a hack to work around a limitation where a template argument cannot
118 // be declared as a friend directly. This is used in the below Singleton
119 // template.
120 template <typename T>
121 struct FriendMaker {
122 typedef T FriendType;
123 };
117 124
118 // The Singleton<Type, Traits, DifferentiatingType> class manages a single 125 // The Singleton<Type, Traits, DifferentiatingType> class manages a single
119 // instance of Type which will be created on first use and will be destroyed at 126 // instance of Type which will be created on first use and will be destroyed at
120 // normal process exit). The Trait::Delete function will not be called on 127 // normal process exit). The Trait::Delete function will not be called on
121 // abnormal process exit. 128 // abnormal process exit.
122 // 129 //
123 // DifferentiatingType is used as a key to differentiate two different 130 // DifferentiatingType is used as a key to differentiate two different
124 // singletons having the same memory allocation functions but serving a 131 // singletons having the same memory allocation functions but serving a
125 // different purpose. This is mainly used for Locks serving different purposes. 132 // different purpose. This is mainly used for Locks serving different purposes.
126 // 133 //
127 // Example usages: (none are preferred, they all result in the same code) 134 // Example usage:
128 // 1. FooClass* ptr = Singleton<FooClass>::get(); 135 //
129 // ptr->Bar(); 136 // In your header:
130 // 2. Singleton<FooClass>()->Bar(); 137 // #include "base/singleton.h"
131 // 3. Singleton<FooClass>::get()->Bar(); 138 // class FooClass {
139 // public:
140 // static FooClass* GetInstance(); <-- See comment below on this.
141 // void Bar() { ... }
142 // private:
143 // FooClass() { ... }
144 // friend struct DefaultSingletonTraits<FooClass>;
145 //
146 // DISALLOW_COPY_AND_ASSIGN(FooClass);
147 // };
148 //
149 // In your source file:
150 // FooClass* FooClass::GetInstance() {
151 // return Singleton<FooClass>::get();
152 // }
153 //
154 // And to call methods on FooClass:
155 // FooClass::GetInstance()->Bar();
156 //
157 // NOTE: It is important that FooClass::GetInstance() is not inlined in the
158 // header, so that when source files from multiple targets include this header
159 // they don't end up with different copies of the inlined code creating multiple
160 // copies of the singleton.
132 // 161 //
133 // Singleton<> has no non-static members and doesn't need to actually be 162 // Singleton<> has no non-static members and doesn't need to actually be
134 // instantiated. It does no harm to instantiate it and use it as a class member 163 // instantiated. It does no harm to instantiate it and use it as a class member
M-A Ruel 2010/12/10 14:52:18 Remove that too, we don't want to encourage multip
Satish 2010/12/10 17:13:48 Done.
135 // or at global level since it is acting as a POD type. 164 // since it is acting as a POD type.
136 // 165 //
137 // This class is itself thread-safe. The underlying Type must of course be 166 // This class is itself thread-safe. The underlying Type must of course be
138 // thread-safe if you want to use it concurrently. Two parameters may be tuned 167 // thread-safe if you want to use it concurrently. Two parameters may be tuned
139 // depending on the user's requirements. 168 // depending on the user's requirements.
140 // 169 //
141 // Glossary: 170 // Glossary:
142 // RAE = kRegisterAtExit 171 // RAE = kRegisterAtExit
143 // 172 //
144 // On every platform, if Traits::RAE is true, the singleton will be destroyed at 173 // On every platform, if Traits::RAE is true, the singleton will be destroyed at
145 // process exit. More precisely it uses base::AtExitManager which requires an 174 // process exit. More precisely it uses base::AtExitManager which requires an
146 // object of this type to be instantiated. AtExitManager mimics the semantics 175 // object of this type to be instantiated. AtExitManager mimics the semantics
147 // of atexit() such as LIFO order but under Windows is safer to call. For more 176 // of atexit() such as LIFO order but under Windows is safer to call. For more
148 // information see at_exit.h. 177 // information see at_exit.h.
149 // 178 //
150 // If Traits::RAE is false, the singleton will not be freed at process exit, 179 // If Traits::RAE is false, the singleton will not be freed at process exit,
151 // thus the singleton will be leaked if it is ever accessed. Traits::RAE 180 // thus the singleton will be leaked if it is ever accessed. Traits::RAE
152 // shouldn't be false unless absolutely necessary. Remember that the heap where 181 // shouldn't be false unless absolutely necessary. Remember that the heap where
153 // the object is allocated may be destroyed by the CRT anyway. 182 // the object is allocated may be destroyed by the CRT anyway.
154 // 183 //
155 // If you want to ensure that your class can only exist as a singleton, make
156 // its constructors private, and make DefaultSingletonTraits<> a friend:
157 //
158 // #include "base/singleton.h"
159 // class FooClass {
160 // public:
161 // void Bar() { ... }
162 // private:
163 // FooClass() { ... }
164 // friend struct DefaultSingletonTraits<FooClass>;
165 //
166 // DISALLOW_COPY_AND_ASSIGN(FooClass);
167 // };
168 //
169 // Caveats: 184 // Caveats:
170 // (a) Every call to get(), operator->() and operator*() incurs some overhead 185 // (a) Every call to get(), operator->() and operator*() incurs some overhead
171 // (16ns on my P4/2.8GHz) to check whether the object has already been 186 // (16ns on my P4/2.8GHz) to check whether the object has already been
172 // initialized. You may wish to cache the result of get(); it will not 187 // initialized. You may wish to cache the result of get(); it will not
173 // change. 188 // change.
174 // 189 //
175 // (b) Your factory function must never throw an exception. This class is not 190 // (b) Your factory function must never throw an exception. This class is not
176 // exception-safe. 191 // exception-safe.
177 // 192 //
178 template <typename Type, 193 template <typename Type,
179 typename Traits = DefaultSingletonTraits<Type>, 194 typename Traits = DefaultSingletonTraits<Type>,
180 typename DifferentiatingType = Type> 195 typename DifferentiatingType = Type>
181 class Singleton { 196 class Singleton {
182 public: 197 private:
198 #if defined(OS_WIN)
199 friend typename FriendMaker<Type>::FriendType;
M-A Ruel 2010/12/10 14:52:18 I think you don't need this utility class; try thi
Satish 2010/12/10 15:04:57 Doesn't work in GCC "expected nested-name-specifie
M-A Ruel 2010/12/10 15:09:42 Try this instead. typedef typename Type Type; frie
Satish 2010/12/10 16:10:11 Yes I tried that too :) didn't work. I'll keep thi
200 #else
201 friend class FriendMaker<Type>::FriendType;
202 #endif
203
183 // This class is safe to be constructed and copy-constructed since it has no 204 // This class is safe to be constructed and copy-constructed since it has no
184 // member. 205 // member.
185 206
186 // Return a pointer to the one true instance of the class. 207 // Return a pointer to the one true instance of the class.
187 static Type* get() { 208 static Type* get() {
188 if (!Traits::kAllowedToAccessOnNonjoinableThread) 209 if (!Traits::kAllowedToAccessOnNonjoinableThread)
189 base::ThreadRestrictions::AssertSingletonAllowed(); 210 base::ThreadRestrictions::AssertSingletonAllowed();
190 211
191 // Our AtomicWord doubles as a spinlock, where a value of 212 // Our AtomicWord doubles as a spinlock, where a value of
192 // kBeingCreatedMarker means the spinlock is being held for creation. 213 // kBeingCreatedMarker means the spinlock is being held for creation.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 if (value != kBeingCreatedMarker) 254 if (value != kBeingCreatedMarker)
234 break; 255 break;
235 PlatformThread::YieldCurrentThread(); 256 PlatformThread::YieldCurrentThread();
236 } 257 }
237 258
238 // See the corresponding HAPPENS_BEFORE above. 259 // See the corresponding HAPPENS_BEFORE above.
239 ANNOTATE_HAPPENS_AFTER(&instance_); 260 ANNOTATE_HAPPENS_AFTER(&instance_);
240 return reinterpret_cast<Type*>(value); 261 return reinterpret_cast<Type*>(value);
241 } 262 }
242 263
243 // Shortcuts. 264 // Shortcuts.
M-A Ruel 2010/12/10 14:52:18 Probably time to remove these shortcuts. Maybe wor
Satish 2010/12/10 17:13:48 Done.
244 Type& operator*() { 265 Type& operator*() {
245 return *get(); 266 return *get();
246 } 267 }
247 268
248 Type* operator->() { 269 Type* operator->() {
249 return get(); 270 return get();
250 } 271 }
251 272
252 private:
M-A Ruel 2010/12/10 14:52:18 Why make it public?
Satish 2010/12/10 17:13:48 This is still private, along with the rest of this
253 // Adapter function for use with AtExit(). This should be called single 273 // Adapter function for use with AtExit(). This should be called single
254 // threaded, so don't use atomic operations. 274 // threaded, so don't use atomic operations.
255 // Calling OnExit while singleton is in use by other threads is a mistake. 275 // Calling OnExit while singleton is in use by other threads is a mistake.
256 static void OnExit(void* unused) { 276 static void OnExit(void* unused) {
257 // AtExit should only ever be register after the singleton instance was 277 // AtExit should only ever be register after the singleton instance was
258 // created. We should only ever get here with a valid instance_ pointer. 278 // created. We should only ever get here with a valid instance_ pointer.
259 Traits::Delete( 279 Traits::Delete(
260 reinterpret_cast<Type*>(base::subtle::NoBarrier_Load(&instance_))); 280 reinterpret_cast<Type*>(base::subtle::NoBarrier_Load(&instance_)));
261 instance_ = 0; 281 instance_ = 0;
262 } 282 }
263 static base::subtle::AtomicWord instance_; 283 static base::subtle::AtomicWord instance_;
264 }; 284 };
265 285
266 template <typename Type, typename Traits, typename DifferentiatingType> 286 template <typename Type, typename Traits, typename DifferentiatingType>
267 base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>:: 287 base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
268 instance_ = 0; 288 instance_ = 0;
269 289
270 #endif // BASE_SINGLETON_H_ 290 #endif // BASE_SINGLETON_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698