Changeset 30527 in webkit for trunk/JavaScriptCore/wtf/ThreadingWin.cpp
- Timestamp:
- Feb 23, 2008, 1:52:07 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/wtf/ThreadingWin.cpp
r30522 r30527 25 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * ============================================================================= 29 * Note: The implementation of condition variables under the Windows 30 * plaform was based on that of the excellent BOOST C++ library. It 31 * has been rewritten to fit in with the WebKit architecture and to 32 * use its coding conventions. 33 * ============================================================================= 34 * 35 * The Boost license is virtually identical to the Apple variation at the 36 * top of this file, but is included here for completeness: 37 * 38 * Boost Software License - Version 1.0 - August 17th, 2003 39 * 40 * Permission is hereby granted, free of charge, to any person or organization 41 * obtaining a copy of the software and accompanying documentation covered by 42 * this license (the "Software") to use, reproduce, display, distribute, 43 * execute, and transmit the Software, and to prepare derivative works of the 44 * Software, and to permit third-parties to whom the Software is furnished to 45 * do so, all subject to the following: 46 * 47 * The copyright notices in the Software and this entire statement, including 48 * the above license grant, this restriction and the following disclaimer, 49 * must be included in all copies of the Software, in whole or in part, and 50 * all derivative works of the Software, unless such copies or derivative 51 * works are solely in the form of machine-executable object code generated by 52 * a source language processor. 53 * 54 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 55 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 56 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 57 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 58 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 59 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 60 * DEALINGS IN THE SOFTWARE. 27 61 */ 28 62 … … 165 199 } 166 200 201 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); 202 203 ThreadCondition::ThreadCondition() 204 { 205 m_condition.m_timedOut = 0; 206 m_condition.m_blocked = 0; 207 m_condition.m_waitingForRemoval = 0; 208 m_condition.m_gate = ::CreateSemaphore(0, 1, 1, 0); 209 m_condition.m_queue = ::CreateSemaphore(0, 0, MaxSemaphoreCount, 0); 210 m_condition.m_mutex = ::CreateMutex(0, 0, 0); 211 212 if (!m_condition.m_gate || !m_condition.m_queue || !m_condition.m_mutex) { 213 if (m_condition.m_gate) 214 ::CloseHandle(m_condition.m_gate); 215 if (m_condition.m_queue) 216 ::CloseHandle(m_condition.m_queue); 217 if (m_condition.m_mutex) 218 ::CloseHandle(m_condition.m_mutex); 219 } 220 } 221 222 ThreadCondition::~ThreadCondition() 223 { 224 ::CloseHandle(m_condition.m_gate); 225 ::CloseHandle(m_condition.m_queue); 226 ::CloseHandle(m_condition.m_mutex); 227 } 228 229 void ThreadCondition::wait(Mutex& mutex) 230 { 231 PlatformMutex& cs = mutex.impl(); 232 233 // Enter the wait state. 234 DWORD res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); 235 ASSERT(res == WAIT_OBJECT_0); 236 ++m_condition.m_blocked; 237 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); 238 ASSERT(res); 239 240 ::LeaveCriticalSection(&cs.m_internalMutex); 241 242 res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); 243 ASSERT(res == WAIT_OBJECT_0); 244 245 res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); 246 ASSERT(res == WAIT_OBJECT_0); 247 size_t wasWaiting = m_condition.m_waitingForRemoval; 248 size_t wasTimedOut = m_condition.m_timedOut; 249 if (wasWaiting != 0) { 250 if (--m_condition.m_waitingForRemoval == 0) { 251 if (m_condition.m_blocked != 0) { 252 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); // open m_gate 253 ASSERT(res); 254 wasWaiting = 0; 255 } 256 else if (m_condition.m_timedOut != 0) 257 m_condition.m_timedOut = 0; 258 } 259 } else if (++m_condition.m_timedOut == ((std::numeric_limits<unsigned>::max)() / 2)) { 260 // timeout occured, normalize the m_condition.m_timedOut count 261 // this may occur if many calls to wait with a timeout are made and 262 // no call to notify_* is made 263 res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); 264 ASSERT(res == WAIT_OBJECT_0); 265 m_condition.m_blocked -= m_condition.m_timedOut; 266 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); 267 ASSERT(res); 268 m_condition.m_timedOut = 0; 269 } 270 res = ::ReleaseMutex(m_condition.m_mutex); 271 ASSERT(res); 272 273 if (wasWaiting == 1) { 274 for (/**/ ; wasTimedOut; --wasTimedOut) { 275 // better now than spurious later 276 res = ::WaitForSingleObject(m_condition.m_queue, INFINITE); 277 ASSERT(res == WAIT_OBJECT_0); 278 } 279 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); 280 ASSERT(res); 281 } 282 283 ::EnterCriticalSection (&cs.m_internalMutex); 284 } 285 286 void ThreadCondition::signal() 287 { 288 unsigned signals = 0; 289 290 DWORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); 291 ASSERT(res == WAIT_OBJECT_0); 292 293 if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed 294 if (m_condition.m_blocked == 0) { 295 res = ::ReleaseMutex(m_condition.m_mutex); 296 ASSERT(res); 297 return; 298 } 299 300 ++m_condition.m_waitingForRemoval; 301 --m_condition.m_blocked; 302 303 signals = 1; 304 } else { 305 res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); 306 ASSERT(res == WAIT_OBJECT_0); 307 if (m_condition.m_blocked > m_condition.m_timedOut) { 308 if (m_condition.m_timedOut != 0) { 309 m_condition.m_blocked -= m_condition.m_timedOut; 310 m_condition.m_timedOut = 0; 311 } 312 signals = m_condition.m_waitingForRemoval = 1; 313 --m_condition.m_blocked; 314 } else { 315 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); 316 ASSERT(res); 317 } 318 } 319 320 res =::ReleaseMutex(m_condition.m_mutex); 321 ASSERT(res); 322 323 if (signals) { 324 res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); 325 ASSERT(res); 326 } 327 } 328 329 void ThreadCondition::broadcast() 330 { 331 unsigned signals = 0; 332 333 WORD res = ::WaitForSingleObject(m_condition.m_mutex, INFINITE); 334 ASSERT(res == WAIT_OBJECT_0); 335 336 if (m_condition.m_waitingForRemoval != 0) { // the m_gate is already closed 337 if (m_condition.m_blocked == 0) { 338 res = ::ReleaseMutex(m_condition.m_mutex); 339 ASSERT(res); 340 return; 341 } 342 343 m_condition.m_waitingForRemoval += (signals = m_condition.m_blocked); 344 m_condition.m_blocked = 0; 345 } else { 346 res = ::WaitForSingleObject(m_condition.m_gate, INFINITE); 347 ASSERT(res == WAIT_OBJECT_0); 348 if (m_condition.m_blocked > m_condition.m_timedOut) { 349 if (m_condition.m_timedOut != 0) { 350 m_condition.m_blocked -= m_condition.m_timedOut; 351 m_condition.m_timedOut = 0; 352 } 353 signals = m_condition.m_waitingForRemoval = m_condition.m_blocked; 354 m_condition.m_blocked = 0; 355 } else { 356 res = ::ReleaseSemaphore(m_condition.m_gate, 1, 0); 357 ASSERT(res); 358 } 359 } 360 361 res = ::ReleaseMutex(m_condition.m_mutex); 362 ASSERT(res); 363 364 if (signals) { 365 res = ::ReleaseSemaphore(m_condition.m_queue, signals, 0); 366 ASSERT(res); 367 } 368 } 369 167 370 } // namespace WTF
Note:
See TracChangeset
for help on using the changeset viewer.