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