1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _SALHELPER_SINGLETONREF_HXX_ 25 #define _SALHELPER_SINGLETONREF_HXX_ 26 27 //_______________________________________________ 28 // includes 29 30 #include <osl/mutex.hxx> 31 #include "rtl/instance.hxx" 32 #include "osl/diagnose.h" 33 #include "osl/getglobalmutex.hxx" 34 35 //_______________________________________________ 36 // namespace 37 38 namespace salhelper{ 39 40 //_______________________________________________ 41 // definitions 42 43 /** @short template for implementing singleton classes. 44 45 @descr Such classes can be instanciated everytimes they 46 are needed. But the internal wrapped object will 47 be created one times only. Of course its used 48 resources are referenced one times only too. 49 This template hold it alive till the last 50 reference is gone. Further all operations 51 on this reference are threadsafe. Only 52 calls directly to the internal object (which modify 53 its state) must be made threadsafe by the object itself 54 or from outside. 55 56 @attention To prevent the code against race conditions, its not 57 allowed to start operations inside the ctor 58 of the internal wrapped object - especially operations 59 which needs a reference to the same singleton too. 60 61 The only chance to suppress such strange constellations 62 is a lazy-init mechanism. 63 64 <ul> 65 <li>a) The singleton class can provide a special init() 66 method, which must be called as first after creation.</li> 67 <li>b) The singleton class can call a special impl_init() 68 method implicit for every called interface method.</li> 69 </ul> 70 71 Note further that this singleton pattern can work only, if 72 all user of such singleton are located inside the same library! 73 Because static values can't be exported - e.g. from windows libraries. 74 */ 75 template< class SingletonClass > 76 class SingletonRef 77 { 78 //------------------------------------------- 79 // member 80 81 private : 82 83 /** @short pointer to the internal wrapped singleton. */ 84 static SingletonClass* m_pInstance; 85 86 /** @short ref count, which regulate creation and removing of m_pInstance. */ 87 static sal_Int32 m_nRef; 88 89 //------------------------------------------- 90 // interface 91 92 public : 93 94 //--------------------------------------- 95 96 /** @short standard ctor. 97 98 @descr The internal wrapped object is created only, 99 if its ref count was 0. Otherwhise this method 100 does nothing ... except increasing of the internal 101 ref count! 102 */ 103 SingletonRef() 104 { 105 // GLOBAL SAFE -> 106 ::osl::MutexGuard aLock(SingletonRef::ownStaticLock()); 107 108 // must be increased before(!) the check is done. 109 // Otherwhise this check can fail inside the same thread ... 110 ++m_nRef; 111 if (m_nRef == 1) 112 m_pInstance = new SingletonClass(); 113 114 OSL_ENSURE(m_nRef>0 && m_pInstance, "Race? Ref count of singleton >0, but instance is NULL!"); 115 // <- GLOBAL SAFE 116 } 117 118 //--------------------------------------- 119 120 /** @short standard dtor. 121 122 @descr The internal wrapped object is removed only, 123 if its ref count wil be 0. Otherwhise this method 124 does nothing ... except decreasing of the internal 125 ref count! 126 */ 127 ~SingletonRef() 128 { 129 // GLOBAL SAFE -> 130 ::osl::MutexGuard aLock(SingletonRef::ownStaticLock()); 131 132 // must be decreased before(!) the check is done. 133 // Otherwhise this check can fail inside the same thread ... 134 --m_nRef; 135 if (m_nRef == 0) 136 { 137 delete m_pInstance; 138 m_pInstance = 0; 139 } 140 // <- GLOBAL SAFE 141 } 142 143 //--------------------------------------- 144 145 /** @short Allows rSingle->someBodyOp(). 146 */ 147 SingletonClass* operator->() const 148 { 149 // GLOBAL SAFE -> 150 ::osl::MutexGuard aLock(SingletonRef::ownStaticLock()); 151 return m_pInstance; 152 // <- GLOBAL SAFE 153 } 154 155 //--------------------------------------- 156 157 /** @short Allows (*rSingle).someBodyOp(). 158 */ 159 SingletonClass& operator*() const 160 { 161 // GLOBAL SAFE -> 162 ::osl::MutexGuard aLock(SingletonRef::ownStaticLock()); 163 return *m_pInstance; 164 // <- GLOBAL SAFE 165 } 166 167 //------------------------------------------- 168 // helper 169 170 private : 171 172 //--------------------------------------- 173 174 /** @short creates an own mutex for guarding static contents. 175 176 @descr The global mutex the osl library is used one times 177 only to create an own static mutex, which can be used 178 next time to guard own static member operations. 179 */ 180 struct SingletonLockInit 181 { 182 ::osl::Mutex* operator()() 183 { 184 static ::osl::Mutex aInstance; 185 return &aInstance; 186 } 187 }; 188 189 ::osl::Mutex& ownStaticLock() const 190 { 191 return *rtl_Instance< ::osl::Mutex, 192 SingletonLockInit, 193 ::osl::MutexGuard, 194 ::osl::GetGlobalMutex >::create(SingletonLockInit(), ::osl::GetGlobalMutex()); 195 } 196 }; 197 198 template< class SingletonClass > 199 SingletonClass* SingletonRef< SingletonClass >::m_pInstance = 0; 200 201 template< class SingletonClass > 202 sal_Int32 SingletonRef< SingletonClass >::m_nRef = 0; 203 204 } // namespace salhelper 205 206 #endif // _SALHELPER_SINGLETONREF_HXX_ 207