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

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.
135 // or at global level since it is acting as a POD type.
136 // 164 //
137 // This class is itself thread-safe. The underlying Type must of course be 165 // 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 166 // thread-safe if you want to use it concurrently. Two parameters may be tuned
139 // depending on the user's requirements. 167 // depending on the user's requirements.
140 // 168 //
141 // Glossary: 169 // Glossary:
142 // RAE = kRegisterAtExit 170 // RAE = kRegisterAtExit
143 // 171 //
144 // On every platform, if Traits::RAE is true, the singleton will be destroyed at 172 // 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 173 // process exit. More precisely it uses base::AtExitManager which requires an
146 // object of this type to be instantiated. AtExitManager mimics the semantics 174 // 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 175 // of atexit() such as LIFO order but under Windows is safer to call. For more
148 // information see at_exit.h. 176 // information see at_exit.h.
149 // 177 //
150 // If Traits::RAE is false, the singleton will not be freed at process exit, 178 // 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 179 // 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 180 // shouldn't be false unless absolutely necessary. Remember that the heap where
153 // the object is allocated may be destroyed by the CRT anyway. 181 // the object is allocated may be destroyed by the CRT anyway.
154 // 182 //
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: 183 // Caveats:
170 // (a) Every call to get(), operator->() and operator*() incurs some overhead 184 // (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 185 // (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 186 // initialized. You may wish to cache the result of get(); it will not
173 // change. 187 // change.
174 // 188 //
175 // (b) Your factory function must never throw an exception. This class is not 189 // (b) Your factory function must never throw an exception. This class is not
176 // exception-safe. 190 // exception-safe.
177 // 191 //
178 template <typename Type, 192 template <typename Type,
179 typename Traits = DefaultSingletonTraits<Type>, 193 typename Traits = DefaultSingletonTraits<Type>,
180 typename DifferentiatingType = Type> 194 typename DifferentiatingType = Type>
181 class Singleton { 195 class Singleton {
182 public: 196 private:
197 #if defined(OS_WIN)
198 friend typename FriendMaker<Type>::FriendType;
199 #else
200 friend class FriendMaker<Type>::FriendType;
201 #endif
202
183 // This class is safe to be constructed and copy-constructed since it has no 203 // This class is safe to be constructed and copy-constructed since it has no
184 // member. 204 // member.
185 205
186 // Return a pointer to the one true instance of the class. 206 // Return a pointer to the one true instance of the class.
187 static Type* get() { 207 static Type* get() {
188 if (!Traits::kAllowedToAccessOnNonjoinableThread) 208 if (!Traits::kAllowedToAccessOnNonjoinableThread)
189 base::ThreadRestrictions::AssertSingletonAllowed(); 209 base::ThreadRestrictions::AssertSingletonAllowed();
190 210
191 // Our AtomicWord doubles as a spinlock, where a value of 211 // Our AtomicWord doubles as a spinlock, where a value of
192 // kBeingCreatedMarker means the spinlock is being held for creation. 212 // 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) 253 if (value != kBeingCreatedMarker)
234 break; 254 break;
235 PlatformThread::YieldCurrentThread(); 255 PlatformThread::YieldCurrentThread();
236 } 256 }
237 257
238 // See the corresponding HAPPENS_BEFORE above. 258 // See the corresponding HAPPENS_BEFORE above.
239 ANNOTATE_HAPPENS_AFTER(&instance_); 259 ANNOTATE_HAPPENS_AFTER(&instance_);
240 return reinterpret_cast<Type*>(value); 260 return reinterpret_cast<Type*>(value);
241 } 261 }
242 262
243 // Shortcuts.
244 Type& operator*() {
245 return *get();
246 }
247
248 Type* operator->() {
249 return get();
250 }
251
252 private:
253 // Adapter function for use with AtExit(). This should be called single 263 // Adapter function for use with AtExit(). This should be called single
254 // threaded, so don't use atomic operations. 264 // threaded, so don't use atomic operations.
255 // Calling OnExit while singleton is in use by other threads is a mistake. 265 // Calling OnExit while singleton is in use by other threads is a mistake.
256 static void OnExit(void* unused) { 266 static void OnExit(void* unused) {
257 // AtExit should only ever be register after the singleton instance was 267 // AtExit should only ever be register after the singleton instance was
258 // created. We should only ever get here with a valid instance_ pointer. 268 // created. We should only ever get here with a valid instance_ pointer.
259 Traits::Delete( 269 Traits::Delete(
260 reinterpret_cast<Type*>(base::subtle::NoBarrier_Load(&instance_))); 270 reinterpret_cast<Type*>(base::subtle::NoBarrier_Load(&instance_)));
261 instance_ = 0; 271 instance_ = 0;
262 } 272 }
263 static base::subtle::AtomicWord instance_; 273 static base::subtle::AtomicWord instance_;
264 }; 274 };
265 275
266 template <typename Type, typename Traits, typename DifferentiatingType> 276 template <typename Type, typename Traits, typename DifferentiatingType>
267 base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>:: 277 base::subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::
268 instance_ = 0; 278 instance_ = 0;
269 279
270 #endif // BASE_SINGLETON_H_ 280 #endif // BASE_SINGLETON_H_
OLDNEW
« no previous file with comments | « base/path_service.cc ('k') | base/singleton_unittest.cc » ('j') | net/disk_cache/file_win.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698