OLD | NEW |
| (Empty) |
1 // Copyright 2004-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Defines two classes | |
17 // 1. class SingletonBase. | |
18 // 2. template class Singleton. | |
19 // Creation of singletons is a common | |
20 // activity. Use Singleton class to not | |
21 // repeat code every time. | |
22 | |
23 #ifndef OMAHA_COMMON_SINGLETON_H_ | |
24 #define OMAHA_COMMON_SINGLETON_H_ | |
25 | |
26 #include "omaha/base/debug.h" | |
27 #include "omaha/base/synchronized.h" | |
28 | |
29 | |
30 // Very important design pattern. | |
31 // Singleton class can be used in two ways. | |
32 // 1. Pass the class you want to make into Singleton as a | |
33 // template parameter. | |
34 // | |
35 // class SomeClass { | |
36 // protected: | |
37 // SomeClass(){} // note - it is protected | |
38 // ~SomeClass(){} // note - it is protected | |
39 // public: | |
40 // void Foo() {} | |
41 // }; | |
42 // | |
43 // Singleton<SomeClass> s; | |
44 // s::Instance()->Foo(); | |
45 // | |
46 // OR | |
47 // 2. You class can be derived from Singleton in a following way: | |
48 // class SomeClass : public Singleton<SomeClass> { | |
49 // protected: | |
50 // SomeClass(){} | |
51 // ~SomeClass(){} | |
52 // public: | |
53 // void Foo() {} | |
54 // }; | |
55 // | |
56 // SomeClass::Instance()->Foo(); | |
57 // | |
58 // There is no requirement on the class you want to make into | |
59 // Singleton except is has to have constructor that takes nothing. | |
60 // As long as the class has void constructor it can become a singleton. | |
61 // However if you want you class to be trully singleton you have to make | |
62 // it constructors and destructors protected. Than you can only access your | |
63 // class through the singlenot interface Instance(). | |
64 // If simple void constructor is not enough for you class, provide some kind of | |
65 // initialization function, which could be called after the instance is | |
66 // created. | |
67 | |
68 #define kSingletonMutexName kLockPrefix L"Singleton_Creation_Lock" | |
69 | |
70 #ifdef _DEBUG | |
71 #define InstanceReturnTypeDeclaration SingletonProxy<T> | |
72 #define InstanceReturnTypeStatement SingletonProxy<T> | |
73 #else | |
74 #define InstanceReturnTypeDeclaration T* | |
75 #define InstanceReturnTypeStatement | |
76 #endif | |
77 | |
78 template <typename T> class Singleton { | |
79 // Caching pointers to Singletons is very dangerous and goes against | |
80 // Singleton philosophy. So we will return proxy from instance in Debug mode. | |
81 // In release mode we will not go this route for efficiency. | |
82 template <typename T> class SingletonProxy { | |
83 T* data_; | |
84 public: | |
85 explicit SingletonProxy(T* data) : data_(data) {} | |
86 T* operator->() const { | |
87 return data_; | |
88 } | |
89 SingletonProxy& operator=(const SingletonProxy&); | |
90 }; | |
91 | |
92 public: | |
93 Singleton() {} | |
94 | |
95 // Use double-check pattern for efficiency. | |
96 // TODO(omaha): the pattern is broken on multicore. | |
97 static InstanceReturnTypeDeclaration Instance() { | |
98 if(instance_ == NULL) { | |
99 // We use GLock here since LLock will not give us synchronization and | |
100 // SimpleLock will create deadlock if one singleton is created in the | |
101 // constructor of the other singleton. | |
102 GLock creation_lock; | |
103 TCHAR mutex_name[MAX_PATH] = {0}; | |
104 wsprintf(mutex_name, L"%s%d", | |
105 kSingletonMutexName, ::GetCurrentProcessId()); | |
106 | |
107 VERIFY1(creation_lock.Initialize(mutex_name)); | |
108 __mutexScope(creation_lock); | |
109 if(instance_ == NULL) | |
110 instance_ = GetInstance(); | |
111 } | |
112 return InstanceReturnTypeStatement(instance_); | |
113 } | |
114 | |
115 private: | |
116 static T* GetInstance() { | |
117 static MyT my_t; | |
118 return &my_t; | |
119 } | |
120 | |
121 // shared between the same type T. | |
122 static T * instance_; | |
123 | |
124 // Needed to access the protected constructor | |
125 // of a client. | |
126 class MyT : public T { | |
127 }; | |
128 }; | |
129 | |
130 // This instance_ is shared between template of the same type. | |
131 template <typename T> T* Singleton<T>::instance_ = NULL; | |
132 | |
133 #endif // OMAHA_COMMON_SINGLETON_H_ | |
OLD | NEW |