OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // PLEASE READ: Do you really need a singleton? | 5 // PLEASE READ: Do you really need a singleton? |
6 // | 6 // |
7 // Singletons make it hard to determine the lifetime of an object, which can | 7 // Singletons make it hard to determine the lifetime of an object, which can |
8 // lead to buggy code and spurious crashes. | 8 // lead to buggy code and spurious crashes. |
9 // | 9 // |
10 // Instead of adding another singleton into the mix, try to identify either: | 10 // Instead of adding another singleton into the mix, try to identify either: |
11 // a) An existing singleton that can manage your object's lifetime | 11 // a) An existing singleton that can manage your object's lifetime |
12 // b) Locations where you can deterministically create the object and pass | 12 // b) Locations where you can deterministically create the object and pass |
13 // into other objects | 13 // into other objects |
14 // | 14 // |
15 // If you absolutely need a singleton, please keep them as trivial as possible | 15 // If you absolutely need a singleton, please keep them as trivial as possible |
16 // and ideally a leaf dependency. Singletons get problematic when they attempt | 16 // and ideally a leaf dependency. Singletons get problematic when they attempt |
17 // to do too much in their destructor or have circular dependencies. | 17 // to do too much in their destructor or have circular dependencies. |
18 | 18 |
19 #ifndef BASE_MEMORY_SINGLETON_H_ | 19 #ifndef BASE_MEMORY_SINGLETON_H_ |
20 #define BASE_MEMORY_SINGLETON_H_ | 20 #define BASE_MEMORY_SINGLETON_H_ |
21 | 21 |
22 #include "base/at_exit.h" | 22 #include "base/at_exit.h" |
23 #include "base/atomicops.h" | 23 #include "base/atomicops.h" |
24 #include "base/base_export.h" | 24 #include "base/base_export.h" |
| 25 #include "base/logging.h" |
25 #include "base/macros.h" | 26 #include "base/macros.h" |
26 #include "base/memory/aligned_memory.h" | 27 #include "base/memory/aligned_memory.h" |
27 #include "base/threading/thread_restrictions.h" | 28 #include "base/threading/thread_restrictions.h" |
28 | 29 |
29 namespace base { | 30 namespace base { |
30 namespace internal { | 31 namespace internal { |
31 | 32 |
32 // Our AtomicWord doubles as a spinlock, where a value of | 33 // Our AtomicWord doubles as a spinlock, where a value of |
33 // kBeingCreatedMarker means the spinlock is being held for creation. | 34 // kBeingCreatedMarker means the spinlock is being held for creation. |
34 static const subtle::AtomicWord kBeingCreatedMarker = 1; | 35 static const subtle::AtomicWord kBeingCreatedMarker = 1; |
(...skipping 21 matching lines...) Expand all Loading... |
56 | 57 |
57 // Destroys the object. | 58 // Destroys the object. |
58 static void Delete(Type* x) { | 59 static void Delete(Type* x) { |
59 delete x; | 60 delete x; |
60 } | 61 } |
61 | 62 |
62 // Set to true to automatically register deletion of the object on process | 63 // Set to true to automatically register deletion of the object on process |
63 // exit. See below for the required call that makes this happen. | 64 // exit. See below for the required call that makes this happen. |
64 static const bool kRegisterAtExit = true; | 65 static const bool kRegisterAtExit = true; |
65 | 66 |
66 #ifndef NDEBUG | 67 #if DCHECK_IS_ON() |
67 // Set to false to disallow access on a non-joinable thread. This is | 68 // Set to false to disallow access on a non-joinable thread. This is |
68 // different from kRegisterAtExit because StaticMemorySingletonTraits allows | 69 // different from kRegisterAtExit because StaticMemorySingletonTraits allows |
69 // access on non-joinable threads, and gracefully handles this. | 70 // access on non-joinable threads, and gracefully handles this. |
70 static const bool kAllowedToAccessOnNonjoinableThread = false; | 71 static const bool kAllowedToAccessOnNonjoinableThread = false; |
71 #endif | 72 #endif |
72 }; | 73 }; |
73 | 74 |
74 | 75 |
75 // Alternate traits for use with the Singleton<Type>. Identical to | 76 // Alternate traits for use with the Singleton<Type>. Identical to |
76 // DefaultSingletonTraits except that the Singleton will not be cleaned up | 77 // DefaultSingletonTraits except that the Singleton will not be cleaned up |
77 // at exit. | 78 // at exit. |
78 template<typename Type> | 79 template<typename Type> |
79 struct LeakySingletonTraits : public DefaultSingletonTraits<Type> { | 80 struct LeakySingletonTraits : public DefaultSingletonTraits<Type> { |
80 static const bool kRegisterAtExit = false; | 81 static const bool kRegisterAtExit = false; |
81 #ifndef NDEBUG | 82 #if DCHECK_IS_ON() |
82 static const bool kAllowedToAccessOnNonjoinableThread = true; | 83 static const bool kAllowedToAccessOnNonjoinableThread = true; |
83 #endif | 84 #endif |
84 }; | 85 }; |
85 | 86 |
86 | 87 |
87 // Alternate traits for use with the Singleton<Type>. Allocates memory | 88 // Alternate traits for use with the Singleton<Type>. Allocates memory |
88 // for the singleton instance from a static buffer. The singleton will | 89 // for the singleton instance from a static buffer. The singleton will |
89 // be cleaned up at exit, but can't be revived after destruction unless | 90 // be cleaned up at exit, but can't be revived after destruction unless |
90 // the Resurrect() method is called. | 91 // the Resurrect() method is called. |
91 // | 92 // |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 friend Type* Type::GetInstance(); | 221 friend Type* Type::GetInstance(); |
221 | 222 |
222 // Allow TraceLog tests to test tracing after OnExit. | 223 // Allow TraceLog tests to test tracing after OnExit. |
223 friend class internal::DeleteTraceLogForTesting; | 224 friend class internal::DeleteTraceLogForTesting; |
224 | 225 |
225 // This class is safe to be constructed and copy-constructed since it has no | 226 // This class is safe to be constructed and copy-constructed since it has no |
226 // member. | 227 // member. |
227 | 228 |
228 // Return a pointer to the one true instance of the class. | 229 // Return a pointer to the one true instance of the class. |
229 static Type* get() { | 230 static Type* get() { |
230 #ifndef NDEBUG | 231 #if DCHECK_IS_ON() |
231 // Avoid making TLS lookup on release builds. | 232 // Avoid making TLS lookup on release builds. |
232 if (!Traits::kAllowedToAccessOnNonjoinableThread) | 233 if (!Traits::kAllowedToAccessOnNonjoinableThread) |
233 ThreadRestrictions::AssertSingletonAllowed(); | 234 ThreadRestrictions::AssertSingletonAllowed(); |
234 #endif | 235 #endif |
235 | 236 |
236 // The load has acquire memory ordering as the thread which reads the | 237 // The load has acquire memory ordering as the thread which reads the |
237 // instance_ pointer must acquire visibility over the singleton data. | 238 // instance_ pointer must acquire visibility over the singleton data. |
238 subtle::AtomicWord value = subtle::Acquire_Load(&instance_); | 239 subtle::AtomicWord value = subtle::Acquire_Load(&instance_); |
239 if (value != 0 && value != internal::kBeingCreatedMarker) { | 240 if (value != 0 && value != internal::kBeingCreatedMarker) { |
240 return reinterpret_cast<Type*>(value); | 241 return reinterpret_cast<Type*>(value); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 } | 276 } |
276 static subtle::AtomicWord instance_; | 277 static subtle::AtomicWord instance_; |
277 }; | 278 }; |
278 | 279 |
279 template <typename Type, typename Traits, typename DifferentiatingType> | 280 template <typename Type, typename Traits, typename DifferentiatingType> |
280 subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::instance_ = 0; | 281 subtle::AtomicWord Singleton<Type, Traits, DifferentiatingType>::instance_ = 0; |
281 | 282 |
282 } // namespace base | 283 } // namespace base |
283 | 284 |
284 #endif // BASE_MEMORY_SINGLETON_H_ | 285 #endif // BASE_MEMORY_SINGLETON_H_ |
OLD | NEW |