/Users/deen/code/yugabyte-db/src/yb/gutil/singleton.h
Line | Count | Source |
1 | | // Copyright 2003 Google Inc. |
2 | | // |
3 | | // The Singleton<Type> class manages a single instance of Type which will be |
4 | | // created on first use and (usually) never destroyed. |
5 | | // |
6 | | // MyClass* ptr = Singleton<MyClass>::get() |
7 | | // ptr->DoSomething(); |
8 | | // |
9 | | // Singleton<> has no non-static members and is never actually instantiated. |
10 | | // |
11 | | // WARNING: Read go/singletons before using. |
12 | | // |
13 | | // This class is thread safe; the constructor will be run at most once, and |
14 | | // no user will gain access to the object until the constructor is completed. |
15 | | // The underlying Type must of course be thread-safe if you want to use it |
16 | | // concurrently. |
17 | | // |
18 | | // If you want to ensure that your class can only exist as a singleton, make |
19 | | // its constructors private, and make Singleton<> a friend: |
20 | | // |
21 | | // class MySingletonOnlyClass { |
22 | | // public: |
23 | | // void DoSomething() { ... } |
24 | | // private: |
25 | | // DISALLOW_COPY_AND_ASSIGN(MySingletonOnlyClass); |
26 | | // MySingletonOnlyClass() { ... } |
27 | | // friend class Singleton<MySingletonOnlyClass>; |
28 | | // } |
29 | | // |
30 | | // If your singleton requires complex initialization, or does not have a |
31 | | // suitable default constructor, you can provide a specialization of |
32 | | // Singleton<Type>::CreateInstance() to perform the appropriate setup, e.g.: |
33 | | // |
34 | | // template <> |
35 | | // Type* Singleton<VirtualType>::CreateInstance() { return new ConcreteImpl; } |
36 | | // |
37 | | // If you want to initialize something eagerly at startup, rather than lazily |
38 | | // upon use, consider using REGISTER_MODULE_INITIALIZER (in base/googleinit.h). |
39 | | // |
40 | | // This class also allows users to pick a particular instance as the |
41 | | // singleton with InjectInstance(). This enables unittesting and |
42 | | // dependency injection. It must only be used at program startup. |
43 | | // |
44 | | // Caveats: |
45 | | // (a) The instance is normally never destroyed. Destroying a Singleton is |
46 | | // complex and error-prone; C++ books go on about this at great length, |
47 | | // and I have seen no perfect general solution to the problem. |
48 | | // We *do* offer UnsafeReset() which is not thread-safe at all. |
49 | | // |
50 | | // (b) Your class must have a default (no-argument) constructor, or you must |
51 | | // provide a specialization for Singleton<Type>::CreateInstance(). |
52 | | // |
53 | | // (c) Your class's constructor must never throw an exception. |
54 | | // |
55 | | // Singleton::get() is very fast - about 1ns on a 2.4GHz Core 2. |
56 | | |
57 | | // |
58 | | // The following only applies to changes made to this file as part of YugaByte development. |
59 | | // |
60 | | // Portions Copyright (c) YugaByte, Inc. |
61 | | // |
62 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
63 | | // in compliance with the License. You may obtain a copy of the License at |
64 | | // |
65 | | // http://www.apache.org/licenses/LICENSE-2.0 |
66 | | // |
67 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
68 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
69 | | // or implied. See the License for the specific language governing permissions and limitations |
70 | | // under the License. |
71 | | // |
72 | | #ifndef YB_GUTIL_SINGLETON_H |
73 | | #define YB_GUTIL_SINGLETON_H |
74 | | |
75 | | #include <stddef.h> |
76 | | |
77 | | #include <glog/logging.h> |
78 | | |
79 | | #include "yb/gutil/once.h" |
80 | | |
81 | | namespace util { |
82 | | namespace gtl { |
83 | | template <typename SingletonType> class ScopedSingletonOverride; |
84 | | template <typename SingletonType> class ScopedSingletonOverrideNoDelete; |
85 | | } // namespace gtl |
86 | | } // namespace util |
87 | | |
88 | | template <typename Type> |
89 | | class Singleton { |
90 | | public: |
91 | | // Return a pointer to the one true instance of the class. |
92 | 75.2M | static Type* get() { |
93 | 75.2M | GoogleOnceInit(&once_, &Singleton<Type>::Init); |
94 | 75.2M | return instance_; |
95 | 75.2M | } _ZN9SingletonIN2yb19HeapBufferAllocatorEE3getEv Line | Count | Source | 92 | 3.38M | static Type* get() { | 93 | 3.38M | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 3.38M | return instance_; | 95 | 3.38M | } |
external_mini_cluster.cc:_ZN9SingletonIN2yb12_GLOBAL__N_120GlobalLogTailerStateEE3getEv Line | Count | Source | 92 | 10.7k | static Type* get() { | 93 | 10.7k | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 10.7k | return instance_; | 95 | 10.7k | } |
local_tablet_writer.cc:_ZN9SingletonIN2yb6tablet12_GLOBAL__N_123AutoIncrementingCounterEE3getEv Line | Count | Source | 92 | 96.1k | static Type* get() { | 93 | 96.1k | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 96.1k | return instance_; | 95 | 96.1k | } |
_ZN9SingletonIN2yb15EncoderResolverINS0_10faststringEEEE3getEv Line | Count | Source | 92 | 11.2k | static Type* get() { | 93 | 11.2k | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 11.2k | return instance_; | 95 | 11.2k | } |
_ZN9SingletonIN2yb15EncoderResolverINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEE3getEv Line | Count | Source | 92 | 5.90k | static Type* get() { | 93 | 5.90k | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 5.90k | return instance_; | 95 | 5.90k | } |
_ZN9SingletonIN2yb16TypeInfoResolverEE3getEv Line | Count | Source | 92 | 59.4M | static Type* get() { | 93 | 59.4M | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 59.4M | return instance_; | 95 | 59.4M | } |
_ZN9SingletonIN2yb5docdb17DocPgTypeAnalyzerEE3getEv Line | Count | Source | 92 | 49.1k | static Type* get() { | 93 | 49.1k | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 49.1k | return instance_; | 95 | 49.1k | } |
_ZN9SingletonIN2yb5debug8TraceLogEE3getEv Line | Count | Source | 92 | 1.60M | static Type* get() { | 93 | 1.60M | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 1.60M | return instance_; | 95 | 1.60M | } |
_ZN9SingletonIN2yb5debug32TraceEventSyntheticDelayRegistryEE3getEv Line | Count | Source | 92 | 52 | static Type* get() { | 93 | 52 | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 52 | return instance_; | 95 | 52 | } |
_ZN9SingletonIN2yb18flag_tags_internal15FlagTagRegistryEE3getEv Line | Count | Source | 92 | 10.6M | static Type* get() { | 93 | 10.6M | GoogleOnceInit(&once_, &Singleton<Type>::Init); | 94 | 10.6M | return instance_; | 95 | 10.6M | } |
|
96 | | |
97 | | // WARNING!!! This function is not thread-safe and may leak memory. |
98 | | static void UnsafeReset() { |
99 | | delete instance_; |
100 | | instance_ = NULL; |
101 | | once_.state = GOOGLE_ONCE_INTERNAL_INIT; // This is the bad part! |
102 | | } |
103 | | |
104 | | // This function is used to replace the instance used by |
105 | | // Singleton<Type>::get(). It can be used for breaking dependencies. For |
106 | | // unittesting, you probably want to use ScopedSingletonOverride instead. |
107 | | // |
108 | | // This function must be called before Singleton<Type>::get() is |
109 | | // called and before any threads are created. If these assumptions |
110 | | // are violated, anything could happen, but we try to crash in debug |
111 | | // mode and do nothing in production. |
112 | | static void InjectInstance(Type* instance) { |
113 | | injected_instance_ = instance; |
114 | | GoogleOnceInit(&once_, &Singleton<Type>::Inject); |
115 | | injected_instance_ = NULL; // Helps detect leaks in the unittest. |
116 | | if (instance_ != instance) { |
117 | | LOG(DFATAL) << "(jyasskin) InjectInstance() must be called at most once" |
118 | | << " at the start of the program, before the Singleton has" |
119 | | << " been accessed and before any threads have been created." |
120 | | << " Ignoring the call in production."; |
121 | | delete instance; |
122 | | } |
123 | | } |
124 | | |
125 | | private: |
126 | | friend class util::gtl::ScopedSingletonOverride<Type>; |
127 | | friend class util::gtl::ScopedSingletonOverrideNoDelete<Type>; |
128 | | |
129 | | // Create the instance. |
130 | 62.1k | static void Init() { |
131 | 62.1k | instance_ = CreateInstance(); |
132 | 62.1k | } _ZN9SingletonIN2yb19HeapBufferAllocatorEE4InitEv Line | Count | Source | 130 | 5.28k | static void Init() { | 131 | 5.28k | instance_ = CreateInstance(); | 132 | 5.28k | } |
external_mini_cluster.cc:_ZN9SingletonIN2yb12_GLOBAL__N_120GlobalLogTailerStateEE4InitEv Line | Count | Source | 130 | 229 | static void Init() { | 131 | 229 | instance_ = CreateInstance(); | 132 | 229 | } |
local_tablet_writer.cc:_ZN9SingletonIN2yb6tablet12_GLOBAL__N_123AutoIncrementingCounterEE4InitEv Line | Count | Source | 130 | 54 | static void Init() { | 131 | 54 | instance_ = CreateInstance(); | 132 | 54 | } |
_ZN9SingletonIN2yb15EncoderResolverINS0_10faststringEEEE4InitEv Line | Count | Source | 130 | 1.44k | static void Init() { | 131 | 1.44k | instance_ = CreateInstance(); | 132 | 1.44k | } |
_ZN9SingletonIN2yb15EncoderResolverINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEE4InitEv Line | Count | Source | 130 | 5.43k | static void Init() { | 131 | 5.43k | instance_ = CreateInstance(); | 132 | 5.43k | } |
_ZN9SingletonIN2yb16TypeInfoResolverEE4InitEv Line | Count | Source | 130 | 12.4k | static void Init() { | 131 | 12.4k | instance_ = CreateInstance(); | 132 | 12.4k | } |
_ZN9SingletonIN2yb5docdb17DocPgTypeAnalyzerEE4InitEv Line | Count | Source | 130 | 428 | static void Init() { | 131 | 428 | instance_ = CreateInstance(); | 132 | 428 | } |
_ZN9SingletonIN2yb5debug8TraceLogEE4InitEv Line | Count | Source | 130 | 16.2k | static void Init() { | 131 | 16.2k | instance_ = CreateInstance(); | 132 | 16.2k | } |
_ZN9SingletonIN2yb5debug32TraceEventSyntheticDelayRegistryEE4InitEv Line | Count | Source | 130 | 25 | static void Init() { | 131 | 25 | instance_ = CreateInstance(); | 132 | 25 | } |
_ZN9SingletonIN2yb18flag_tags_internal15FlagTagRegistryEE4InitEv Line | Count | Source | 130 | 20.6k | static void Init() { | 131 | 20.6k | instance_ = CreateInstance(); | 132 | 20.6k | } |
|
133 | | |
134 | | // Create and return the instance. You can use Singleton for objects which |
135 | | // require more complex setup by defining a specialization for your type. |
136 | 62.1k | static Type* CreateInstance() { |
137 | | // use ::new to work around a gcc bug when operator new is overloaded |
138 | 62.1k | return ::new Type; |
139 | 62.1k | } _ZN9SingletonIN2yb19HeapBufferAllocatorEE14CreateInstanceEv Line | Count | Source | 136 | 5.28k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 5.28k | return ::new Type; | 139 | 5.28k | } |
external_mini_cluster.cc:_ZN9SingletonIN2yb12_GLOBAL__N_120GlobalLogTailerStateEE14CreateInstanceEv Line | Count | Source | 136 | 229 | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 229 | return ::new Type; | 139 | 229 | } |
local_tablet_writer.cc:_ZN9SingletonIN2yb6tablet12_GLOBAL__N_123AutoIncrementingCounterEE14CreateInstanceEv Line | Count | Source | 136 | 54 | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 54 | return ::new Type; | 139 | 54 | } |
_ZN9SingletonIN2yb15EncoderResolverINS0_10faststringEEEE14CreateInstanceEv Line | Count | Source | 136 | 1.44k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 1.44k | return ::new Type; | 139 | 1.44k | } |
_ZN9SingletonIN2yb15EncoderResolverINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEEEE14CreateInstanceEv Line | Count | Source | 136 | 5.43k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 5.43k | return ::new Type; | 139 | 5.43k | } |
_ZN9SingletonIN2yb16TypeInfoResolverEE14CreateInstanceEv Line | Count | Source | 136 | 12.4k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 12.4k | return ::new Type; | 139 | 12.4k | } |
_ZN9SingletonIN2yb5docdb17DocPgTypeAnalyzerEE14CreateInstanceEv Line | Count | Source | 136 | 428 | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 428 | return ::new Type; | 139 | 428 | } |
_ZN9SingletonIN2yb5debug8TraceLogEE14CreateInstanceEv Line | Count | Source | 136 | 16.2k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 16.2k | return ::new Type; | 139 | 16.2k | } |
_ZN9SingletonIN2yb5debug32TraceEventSyntheticDelayRegistryEE14CreateInstanceEv Line | Count | Source | 136 | 25 | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 25 | return ::new Type; | 139 | 25 | } |
_ZN9SingletonIN2yb18flag_tags_internal15FlagTagRegistryEE14CreateInstanceEv Line | Count | Source | 136 | 20.6k | static Type* CreateInstance() { | 137 | | // use ::new to work around a gcc bug when operator new is overloaded | 138 | 20.6k | return ::new Type; | 139 | 20.6k | } |
|
140 | | |
141 | | // Inject the instance. |
142 | | static void Inject() { |
143 | | instance_ = injected_instance_; |
144 | | } |
145 | | |
146 | | // Used by ScopedSingletonOverride. Definitely not threadsafe. No one |
147 | | // should be calling this other than ScopedSingletonOverride (which has |
148 | | // friend access to do this and makes sure it calls get() first). |
149 | | static void OverrideSingleton(Type* override_instance) { |
150 | | instance_ = override_instance; |
151 | | } |
152 | | |
153 | | static GoogleOnceType once_; |
154 | | static Type* instance_; |
155 | | static Type* injected_instance_; |
156 | | }; |
157 | | |
158 | | template <typename Type> |
159 | | GoogleOnceType Singleton<Type>::once_ = GOOGLE_ONCE_INIT; |
160 | | |
161 | | template <typename Type> |
162 | | Type* Singleton<Type>::instance_ = NULL; |
163 | | |
164 | | template <typename Type> |
165 | | Type* Singleton<Type>::injected_instance_ = NULL; |
166 | | |
167 | | #endif // YB_GUTIL_SINGLETON_H |