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