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