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