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 __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_ 25 #define __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_ 26 27 //_________________________________________________________________________________________________________________ 28 // my own includes 29 //_________________________________________________________________________________________________________________ 30 31 #include <threadhelp/inoncopyable.h> 32 #include <threadhelp/irwlock.h> 33 34 //#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_ 35 //#include <threadhelp/threadhelpbase.hxx> 36 //#endif 37 38 //_________________________________________________________________________________________________________________ 39 // interface includes 40 //_________________________________________________________________________________________________________________ 41 42 //_________________________________________________________________________________________________________________ 43 // other includes 44 //_________________________________________________________________________________________________________________ 45 46 //_________________________________________________________________________________________________________________ 47 // namespace 48 //_________________________________________________________________________________________________________________ 49 50 namespace framework{ 51 52 //_________________________________________________________________________________________________________________ 53 // const 54 //_________________________________________________________________________________________________________________ 55 56 //_________________________________________________________________________________________________________________ 57 // declarations 58 //_________________________________________________________________________________________________________________ 59 60 /*-************************************************************************************************************//** 61 @short implement a guard to set write locks 62 @descr This guard should be used to set a lock for reading AND writing object internal member. 63 We never need a own mutex to safe our internal member access - because 64 a guard is used as function-local member only. There exist no multithreaded access to it really ... 65 66 @attention a) To prevent us against wrong using, the default ctor, copy ctor and the =operator are maked private! 67 b) Use interface "IRWLock" of set LockHelper only - because we must support a finer granularity of locking. 68 Interface "IMutex" should be used by easier guard implementations ... like "ResetableGuard"! 69 70 @implements - 71 @base INonCopyable 72 73 @devstatus ready to use 74 *//*-*************************************************************************************************************/ 75 class WriteGuard : private INonCopyable 76 { 77 //------------------------------------------------------------------------------------------------------------- 78 // public methods 79 //------------------------------------------------------------------------------------------------------------- 80 public: 81 82 /*-****************************************************************************************************//** 83 @short ctor 84 @descr These ctors initialize the guard with a reference to used lock member of object to protect. 85 Null isn't allowed as value! 86 87 @seealso - 88 89 @param "pLock" ,reference to used lock member of object to protect 90 @param "rLock" ,reference to used lock member of object to protect 91 @return - 92 93 @onerror - 94 *//*-*****************************************************************************************************/ 95 inline WriteGuard( IRWLock* pLock ) 96 : m_pLock ( pLock ) 97 , m_eMode ( E_NOLOCK ) 98 { 99 lock(); 100 } 101 102 //********************************************************************************************************* 103 inline WriteGuard( IRWLock& rLock ) 104 : m_pLock ( &rLock ) 105 , m_eMode ( E_NOLOCK ) 106 { 107 lock(); 108 } 109 110 /*-****************************************************************************************************//** 111 @short dtor 112 @descr We unlock the used lock member automatically if user forget it. 113 114 @seealso - 115 116 @param - 117 @return - 118 119 @onerror - 120 *//*-*****************************************************************************************************/ 121 inline ~WriteGuard() 122 { 123 unlock(); 124 } 125 126 /*-****************************************************************************************************//** 127 @short set write lock 128 @descr Call this method to set the write lock. The call will block till all current threads are synchronized! 129 130 @seealso method unlock() 131 132 @param - 133 @return - 134 135 @onerror - 136 *//*-*****************************************************************************************************/ 137 inline void lock() 138 { 139 switch( m_eMode ) 140 { 141 case E_NOLOCK : { 142 // Acquire write access and set return state. 143 // Mode is set later if it was successful! 144 m_pLock->acquireWriteAccess(); 145 m_eMode = E_WRITELOCK; 146 } 147 break; 148 case E_READLOCK : { 149 // User has downgrade to read access before! 150 // We must release it before we can set a new write access! 151 m_pLock->releaseReadAccess(); 152 m_pLock->acquireWriteAccess(); 153 m_eMode = E_WRITELOCK; 154 } 155 break; 156 default: break; // nothing to do 157 } 158 } 159 160 /*-****************************************************************************************************//** 161 @short unset write lock 162 @descr Call this method to unlock the rw-lock temp.! 163 Normaly we do it at dtor automatically for you ... 164 165 @seealso method lock() 166 167 @param - 168 @return - 169 170 @onerror - 171 *//*-*****************************************************************************************************/ 172 inline void unlock() 173 { 174 switch( m_eMode ) 175 { 176 case E_READLOCK : { 177 // User has downgraded to a read lock before! 178 // => There isn't really a write lock ... 179 m_pLock->releaseReadAccess(); 180 m_eMode = E_NOLOCK; 181 } 182 break; 183 case E_WRITELOCK : { 184 m_pLock->releaseWriteAccess(); 185 m_eMode = E_NOLOCK; 186 } 187 break; 188 default: break; // nothing to do 189 } 190 } 191 192 /*-****************************************************************************************************//** 193 @short downgrade write access to read access without new blocking! 194 @descr If this write lock is set you can change it to a "read lock". 195 An "upgrade" is the same like new calling "lock()"! 196 197 @seealso - 198 199 @param - 200 @return - 201 202 @onerror - 203 *//*-*****************************************************************************************************/ 204 inline void downgrade() 205 { 206 if( m_eMode == E_WRITELOCK ) 207 { 208 m_pLock->downgradeWriteAccess(); 209 m_eMode = E_READLOCK; 210 } 211 } 212 213 /*-****************************************************************************************************//** 214 @short return internal states 215 @descr For user they dont know what they are doing ... 216 217 @seealso - 218 219 @param - 220 @return Current set lock mode. 221 222 @onerror No error should occur. 223 *//*-*****************************************************************************************************/ 224 inline ELockMode getMode() const 225 { 226 return m_eMode; 227 } 228 229 //------------------------------------------------------------------------------------------------------------- 230 // private methods 231 //------------------------------------------------------------------------------------------------------------- 232 private: 233 234 /*-****************************************************************************************************//** 235 @short disable using of these functions! 236 @descr It's not allowed to use this methods. Different problem can occur otherwise. 237 Thats why we disable it by make it private. 238 239 @seealso other ctor 240 241 @param - 242 @return - 243 244 @onerror - 245 *//*-*****************************************************************************************************/ 246 WriteGuard(); 247 248 //------------------------------------------------------------------------------------------------------------- 249 // private member 250 //------------------------------------------------------------------------------------------------------------- 251 private: 252 253 IRWLock* m_pLock ; /// reference to lock-member of protected object 254 ELockMode m_eMode ; /// protection against multiple lock calls without unlock and difference between supported lock modi 255 256 }; // class WriteGuard 257 258 } // namespace framework 259 260 #endif // #ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_ 261