| 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 |