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_GATE_HXX_ 25*b1cdbd2cSJim Jagielski #define __FRAMEWORK_THREADHELP_GATE_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/igate.h> 33*b1cdbd2cSJim Jagielski 34*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 35*b1cdbd2cSJim Jagielski // interface includes 36*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 39*b1cdbd2cSJim Jagielski // other includes 40*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 41*b1cdbd2cSJim Jagielski #include <osl/mutex.hxx> 42*b1cdbd2cSJim Jagielski #include <osl/conditn.hxx> 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 45*b1cdbd2cSJim Jagielski // namespace 46*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 47*b1cdbd2cSJim Jagielski 48*b1cdbd2cSJim Jagielski namespace framework{ 49*b1cdbd2cSJim Jagielski 50*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 51*b1cdbd2cSJim Jagielski // const 52*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 55*b1cdbd2cSJim Jagielski // declarations 56*b1cdbd2cSJim Jagielski //_________________________________________________________________________________________________________________ 57*b1cdbd2cSJim Jagielski 58*b1cdbd2cSJim Jagielski /*-************************************************************************************************************//** 59*b1cdbd2cSJim Jagielski @short implement a gate to block multiple threads at same time or unblock all 60*b1cdbd2cSJim Jagielski @descr A gate can be used as a negative-condition! You can open a "door" - wait() will not block ... 61*b1cdbd2cSJim Jagielski or you can close it - wait() blocks till open() is called again. 62*b1cdbd2cSJim Jagielski As a special feature you can open the gate a little bit by sing openGap(). 63*b1cdbd2cSJim Jagielski Then all currently waiting threads are running immediately - but new ones are blocked! 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski @attention To prevent us against wrong using, the default ctor, copy ctor and the =operator are maked private! 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski @implements IGate 68*b1cdbd2cSJim Jagielski @base IGate 69*b1cdbd2cSJim Jagielski INonCopyable 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski @devstatus ready to use 72*b1cdbd2cSJim Jagielski *//*-*************************************************************************************************************/ 73*b1cdbd2cSJim Jagielski class Gate : public IGate 74*b1cdbd2cSJim Jagielski , private INonCopyable 75*b1cdbd2cSJim Jagielski { 76*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------- 77*b1cdbd2cSJim Jagielski // public methods 78*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------- 79*b1cdbd2cSJim Jagielski public: 80*b1cdbd2cSJim Jagielski 81*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 82*b1cdbd2cSJim Jagielski @short ctor 83*b1cdbd2cSJim Jagielski @descr These initialize the object right as an open gate. 84*b1cdbd2cSJim Jagielski 85*b1cdbd2cSJim Jagielski @seealso - 86*b1cdbd2cSJim Jagielski 87*b1cdbd2cSJim Jagielski @param - 88*b1cdbd2cSJim Jagielski @return - 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski @onerror - 91*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ Gate()92*b1cdbd2cSJim Jagielski inline Gate() 93*b1cdbd2cSJim Jagielski : m_bClosed ( sal_False ) 94*b1cdbd2cSJim Jagielski , m_bGapOpen ( sal_False ) 95*b1cdbd2cSJim Jagielski { 96*b1cdbd2cSJim Jagielski open(); 97*b1cdbd2cSJim Jagielski } 98*b1cdbd2cSJim Jagielski 99*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 100*b1cdbd2cSJim Jagielski @short dtor 101*b1cdbd2cSJim Jagielski @descr Is user forget it - we open the gate ... 102*b1cdbd2cSJim Jagielski blocked threads can running ... but I don't know 103*b1cdbd2cSJim Jagielski if it's right - we are destroyed yet!? 104*b1cdbd2cSJim Jagielski 105*b1cdbd2cSJim Jagielski @seealso - 106*b1cdbd2cSJim Jagielski 107*b1cdbd2cSJim Jagielski @param - 108*b1cdbd2cSJim Jagielski @return - 109*b1cdbd2cSJim Jagielski 110*b1cdbd2cSJim Jagielski @onerror - 111*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ ~Gate()112*b1cdbd2cSJim Jagielski inline virtual ~Gate() 113*b1cdbd2cSJim Jagielski { 114*b1cdbd2cSJim Jagielski open(); 115*b1cdbd2cSJim Jagielski } 116*b1cdbd2cSJim Jagielski 117*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 118*b1cdbd2cSJim Jagielski @interface IGate 119*b1cdbd2cSJim Jagielski @short open the gate 120*b1cdbd2cSJim Jagielski @descr A wait() call will not block then. 121*b1cdbd2cSJim Jagielski 122*b1cdbd2cSJim Jagielski @seealso method close() 123*b1cdbd2cSJim Jagielski 124*b1cdbd2cSJim Jagielski @param - 125*b1cdbd2cSJim Jagielski @return - 126*b1cdbd2cSJim Jagielski 127*b1cdbd2cSJim Jagielski @onerror - 128*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ open()129*b1cdbd2cSJim Jagielski inline virtual void open() 130*b1cdbd2cSJim Jagielski { 131*b1cdbd2cSJim Jagielski // We must safe access to our internal member! 132*b1cdbd2cSJim Jagielski ::osl::MutexGuard aLock( m_aAccessLock ); 133*b1cdbd2cSJim Jagielski // Set condition -> wait don't block any longer -> gate is open 134*b1cdbd2cSJim Jagielski m_aPassage.set(); 135*b1cdbd2cSJim Jagielski // Check if operation was successful! 136*b1cdbd2cSJim Jagielski // Check returns false if condition isn't set => m_bClosed will be true then => we must return false; opening failed 137*b1cdbd2cSJim Jagielski m_bClosed = ( m_aPassage.check() == sal_False ); 138*b1cdbd2cSJim Jagielski } 139*b1cdbd2cSJim Jagielski 140*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 141*b1cdbd2cSJim Jagielski @interface IGate 142*b1cdbd2cSJim Jagielski @short close the gate 143*b1cdbd2cSJim Jagielski @descr A wait() call will block then. 144*b1cdbd2cSJim Jagielski 145*b1cdbd2cSJim Jagielski @seealso method open() 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski @param - 148*b1cdbd2cSJim Jagielski @return - 149*b1cdbd2cSJim Jagielski 150*b1cdbd2cSJim Jagielski @onerror - 151*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ close()152*b1cdbd2cSJim Jagielski inline virtual void close() 153*b1cdbd2cSJim Jagielski { 154*b1cdbd2cSJim Jagielski // We must safe access to our internal member! 155*b1cdbd2cSJim Jagielski ::osl::MutexGuard aLock( m_aAccessLock ); 156*b1cdbd2cSJim Jagielski // Reset condition -> wait blocks now -> gate is closed 157*b1cdbd2cSJim Jagielski m_aPassage.reset(); 158*b1cdbd2cSJim Jagielski // Check if operation was successful! 159*b1cdbd2cSJim Jagielski // Check returns false if condition was reseted => m_bClosed will be true then => we can return true; closing ok 160*b1cdbd2cSJim Jagielski m_bClosed = ( m_aPassage.check() == sal_False ); 161*b1cdbd2cSJim Jagielski } 162*b1cdbd2cSJim Jagielski 163*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 164*b1cdbd2cSJim Jagielski @interface IGate 165*b1cdbd2cSJim Jagielski @short open gate for current waiting threads 166*b1cdbd2cSJim Jagielski @descr All current waiting threads stand in wait() at line "m_aPassage.wait()" ... 167*b1cdbd2cSJim Jagielski With this call you can open the passage for these waiting ones. 168*b1cdbd2cSJim Jagielski The "gap" is closed by any new thread which call wait() automaticly! 169*b1cdbd2cSJim Jagielski 170*b1cdbd2cSJim Jagielski @seealso method wait() 171*b1cdbd2cSJim Jagielski @seealso method open() 172*b1cdbd2cSJim Jagielski 173*b1cdbd2cSJim Jagielski @param - 174*b1cdbd2cSJim Jagielski @return - 175*b1cdbd2cSJim Jagielski 176*b1cdbd2cSJim Jagielski @onerror - 177*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ openGap()178*b1cdbd2cSJim Jagielski inline virtual void openGap() 179*b1cdbd2cSJim Jagielski { 180*b1cdbd2cSJim Jagielski // We must safe access to our internal member! 181*b1cdbd2cSJim Jagielski ::osl::MutexGuard aLock( m_aAccessLock ); 182*b1cdbd2cSJim Jagielski // Open passage for current waiting threads. 183*b1cdbd2cSJim Jagielski m_aPassage.set(); 184*b1cdbd2cSJim Jagielski // Check state of condition. 185*b1cdbd2cSJim Jagielski // If condition is set check() returns true => m_bGapOpen will be true too => we can use it as return value. 186*b1cdbd2cSJim Jagielski m_bGapOpen = ( m_aPassage.check() == sal_True ); 187*b1cdbd2cSJim Jagielski } 188*b1cdbd2cSJim Jagielski 189*b1cdbd2cSJim Jagielski /*-****************************************************************************************************//** 190*b1cdbd2cSJim Jagielski @interface IGate 191*b1cdbd2cSJim Jagielski @short must be called to pass the gate 192*b1cdbd2cSJim Jagielski @descr If gate "open" => wait() will not block. 193*b1cdbd2cSJim Jagielski If gate "closed" => wait() will block till somewhere open it again. 194*b1cdbd2cSJim Jagielski If gap "open" => currently waiting threads unblocked, new ones blocked 195*b1cdbd2cSJim Jagielski 196*b1cdbd2cSJim Jagielski @seealso method wait() 197*b1cdbd2cSJim Jagielski @seealso method open() 198*b1cdbd2cSJim Jagielski 199*b1cdbd2cSJim Jagielski @param "pTimeOut", optional parameter to wait a certain time 200*b1cdbd2cSJim Jagielski @return true, if wait was successful (gate was opened) 201*b1cdbd2cSJim Jagielski false, if condition has an error or timeout was reached! 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski @onerror We return false. 204*b1cdbd2cSJim Jagielski *//*-*****************************************************************************************************/ wait(const TimeValue * pTimeOut=NULL)205*b1cdbd2cSJim Jagielski inline virtual sal_Bool wait( const TimeValue* pTimeOut = NULL ) 206*b1cdbd2cSJim Jagielski { 207*b1cdbd2cSJim Jagielski // We must safe access to our internal member! 208*b1cdbd2cSJim Jagielski ::osl::ClearableMutexGuard aLock( m_aAccessLock ); 209*b1cdbd2cSJim Jagielski // If gate not closed - caller can pass it. 210*b1cdbd2cSJim Jagielski sal_Bool bSuccessful = sal_True; 211*b1cdbd2cSJim Jagielski if( m_bClosed == sal_True ) 212*b1cdbd2cSJim Jagielski { 213*b1cdbd2cSJim Jagielski // Otherwise first new thread must close an open gap! 214*b1cdbd2cSJim Jagielski if( m_bGapOpen == sal_True ) 215*b1cdbd2cSJim Jagielski { 216*b1cdbd2cSJim Jagielski m_bGapOpen = sal_False; 217*b1cdbd2cSJim Jagielski m_aPassage.reset(); 218*b1cdbd2cSJim Jagielski } 219*b1cdbd2cSJim Jagielski // Then we must release used access lock - 220*b1cdbd2cSJim Jagielski // because next call will block ... 221*b1cdbd2cSJim Jagielski // and if we hold the access lock nobody else can use this object without a dadlock! 222*b1cdbd2cSJim Jagielski aLock.clear(); 223*b1cdbd2cSJim Jagielski // Wait for opening gate ... 224*b1cdbd2cSJim Jagielski bSuccessful = ( m_aPassage.wait( pTimeOut ) == ::osl::Condition::result_ok ); 225*b1cdbd2cSJim Jagielski } 226*b1cdbd2cSJim Jagielski 227*b1cdbd2cSJim Jagielski return bSuccessful; 228*b1cdbd2cSJim Jagielski } 229*b1cdbd2cSJim Jagielski 230*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------- 231*b1cdbd2cSJim Jagielski // private member 232*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------------------------------------- 233*b1cdbd2cSJim Jagielski private: 234*b1cdbd2cSJim Jagielski 235*b1cdbd2cSJim Jagielski ::osl::Mutex m_aAccessLock ; 236*b1cdbd2cSJim Jagielski ::osl::Condition m_aPassage ; 237*b1cdbd2cSJim Jagielski sal_Bool m_bClosed ; 238*b1cdbd2cSJim Jagielski sal_Bool m_bGapOpen ; 239*b1cdbd2cSJim Jagielski 240*b1cdbd2cSJim Jagielski }; // class Gate 241*b1cdbd2cSJim Jagielski 242*b1cdbd2cSJim Jagielski } // namespace framework 243*b1cdbd2cSJim Jagielski 244*b1cdbd2cSJim Jagielski #endif // #ifndef __FRAMEWORK_THREADHELP_GATE_HXX_ 245