| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Google Inc. All rights reserved. | 3 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 4 * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. | 4 * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 #include "wtf/dtoa/cached-powers.h" | 101 #include "wtf/dtoa/cached-powers.h" |
| 102 #include <errno.h> | 102 #include <errno.h> |
| 103 #include <process.h> | 103 #include <process.h> |
| 104 #include <windows.h> | 104 #include <windows.h> |
| 105 | 105 |
| 106 namespace WTF { | 106 namespace WTF { |
| 107 | 107 |
| 108 // THREADNAME_INFO comes from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.
aspx>. | 108 // THREADNAME_INFO comes from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.
aspx>. |
| 109 #pragma pack(push, 8) | 109 #pragma pack(push, 8) |
| 110 typedef struct tagTHREADNAME_INFO { | 110 typedef struct tagTHREADNAME_INFO { |
| 111 DWORD dwType; // must be 0x1000 | 111 DWORD dwType; // must be 0x1000 |
| 112 LPCSTR szName; // pointer to name (in user addr space) | 112 LPCSTR szName; // pointer to name (in user addr space) |
| 113 DWORD dwThreadID; // thread ID (-1=caller thread) | 113 DWORD dwThreadID; // thread ID (-1=caller thread) |
| 114 DWORD dwFlags; // reserved for future use, must be zero | 114 DWORD dwFlags; // reserved for future use, must be zero |
| 115 } THREADNAME_INFO; | 115 } THREADNAME_INFO; |
| 116 #pragma pack(pop) | 116 #pragma pack(pop) |
| 117 | 117 |
| 118 static Mutex* atomicallyInitializedStaticMutex; | 118 static Mutex* atomicallyInitializedStaticMutex; |
| 119 | 119 |
| 120 void lockAtomicallyInitializedStaticMutex() | 120 void lockAtomicallyInitializedStaticMutex() { |
| 121 { | 121 ASSERT(atomicallyInitializedStaticMutex); |
| 122 ASSERT(atomicallyInitializedStaticMutex); | 122 atomicallyInitializedStaticMutex->lock(); |
| 123 atomicallyInitializedStaticMutex->lock(); | 123 } |
| 124 } | 124 |
| 125 | 125 void unlockAtomicallyInitializedStaticMutex() { |
| 126 void unlockAtomicallyInitializedStaticMutex() | 126 atomicallyInitializedStaticMutex->unlock(); |
| 127 { | 127 } |
| 128 atomicallyInitializedStaticMutex->unlock(); | 128 |
| 129 } | 129 void initializeThreading() { |
| 130 | 130 // This should only be called once. |
| 131 void initializeThreading() | 131 ASSERT(!atomicallyInitializedStaticMutex); |
| 132 { | 132 |
| 133 // This should only be called once. | 133 // StringImpl::empty() does not construct its static string in a threadsafe fa
shion, |
| 134 ASSERT(!atomicallyInitializedStaticMutex); | 134 // so ensure it has been initialized from here. |
| 135 | 135 StringImpl::empty(); |
| 136 // StringImpl::empty() does not construct its static string in a threadsafe
fashion, | 136 StringImpl::empty16Bit(); |
| 137 // so ensure it has been initialized from here. | 137 atomicallyInitializedStaticMutex = new Mutex; |
| 138 StringImpl::empty(); | 138 wtfThreadData(); |
| 139 StringImpl::empty16Bit(); | 139 s_dtoaP5Mutex = new Mutex; |
| 140 atomicallyInitializedStaticMutex = new Mutex; | 140 initializeDates(); |
| 141 wtfThreadData(); | 141 // Force initialization of static DoubleToStringConverter converter variable |
| 142 s_dtoaP5Mutex = new Mutex; | 142 // inside EcmaScriptConverter function while we are in single thread mode. |
| 143 initializeDates(); | 143 double_conversion::DoubleToStringConverter::EcmaScriptConverter(); |
| 144 // Force initialization of static DoubleToStringConverter converter variable | 144 } |
| 145 // inside EcmaScriptConverter function while we are in single thread mode. | 145 |
| 146 double_conversion::DoubleToStringConverter::EcmaScriptConverter(); | 146 ThreadIdentifier currentThread() { |
| 147 } | 147 return static_cast<ThreadIdentifier>(GetCurrentThreadId()); |
| 148 | 148 } |
| 149 ThreadIdentifier currentThread() | 149 |
| 150 { | 150 MutexBase::MutexBase(bool recursive) { |
| 151 return static_cast<ThreadIdentifier>(GetCurrentThreadId()); | 151 m_mutex.m_recursionCount = 0; |
| 152 } | 152 InitializeCriticalSection(&m_mutex.m_internalMutex); |
| 153 | 153 } |
| 154 MutexBase::MutexBase(bool recursive) | 154 |
| 155 { | 155 MutexBase::~MutexBase() { |
| 156 m_mutex.m_recursionCount = 0; | 156 DeleteCriticalSection(&m_mutex.m_internalMutex); |
| 157 InitializeCriticalSection(&m_mutex.m_internalMutex); | 157 } |
| 158 } | 158 |
| 159 | 159 void MutexBase::lock() { |
| 160 MutexBase::~MutexBase() | 160 EnterCriticalSection(&m_mutex.m_internalMutex); |
| 161 { | 161 ++m_mutex.m_recursionCount; |
| 162 DeleteCriticalSection(&m_mutex.m_internalMutex); | 162 } |
| 163 } | 163 |
| 164 | 164 void MutexBase::unlock() { |
| 165 void MutexBase::lock() | 165 ASSERT(m_mutex.m_recursionCount); |
| 166 { | 166 --m_mutex.m_recursionCount; |
| 167 EnterCriticalSection(&m_mutex.m_internalMutex); | 167 LeaveCriticalSection(&m_mutex.m_internalMutex); |
| 168 ++m_mutex.m_recursionCount; | 168 } |
| 169 } | 169 |
| 170 | 170 bool Mutex::tryLock() { |
| 171 void MutexBase::unlock() | 171 // This method is modeled after the behavior of pthread_mutex_trylock, |
| 172 { | 172 // which will return an error if the lock is already owned by the |
| 173 ASSERT(m_mutex.m_recursionCount); | 173 // current thread. Since the primitive Win32 'TryEnterCriticalSection' |
| 174 --m_mutex.m_recursionCount; | 174 // treats this as a successful case, it changes the behavior of several |
| 175 LeaveCriticalSection(&m_mutex.m_internalMutex); | 175 // tests in WebKit that check to see if the current thread already |
| 176 } | 176 // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord) |
| 177 | 177 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); |
| 178 bool Mutex::tryLock() | 178 |
| 179 { | 179 if (result != 0) { // We got the lock |
| 180 // This method is modeled after the behavior of pthread_mutex_trylock, | 180 // If this thread already had the lock, we must unlock and return |
| 181 // which will return an error if the lock is already owned by the | 181 // false since this is a non-recursive mutex. This is to mimic the |
| 182 // current thread. Since the primitive Win32 'TryEnterCriticalSection' | 182 // behavior of POSIX's pthread_mutex_trylock. We don't do this |
| 183 // treats this as a successful case, it changes the behavior of several | 183 // check in the lock method (presumably due to performance?). This |
| 184 // tests in WebKit that check to see if the current thread already | 184 // means lock() will succeed even if the current thread has already |
| 185 // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord) | 185 // entered the critical section. |
| 186 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); | 186 if (m_mutex.m_recursionCount > 0) { |
| 187 | 187 LeaveCriticalSection(&m_mutex.m_internalMutex); |
| 188 if (result != 0) { // We got the lock | 188 return false; |
| 189 // If this thread already had the lock, we must unlock and return | |
| 190 // false since this is a non-recursive mutex. This is to mimic the | |
| 191 // behavior of POSIX's pthread_mutex_trylock. We don't do this | |
| 192 // check in the lock method (presumably due to performance?). This | |
| 193 // means lock() will succeed even if the current thread has already | |
| 194 // entered the critical section. | |
| 195 if (m_mutex.m_recursionCount > 0) { | |
| 196 LeaveCriticalSection(&m_mutex.m_internalMutex); | |
| 197 return false; | |
| 198 } | |
| 199 ++m_mutex.m_recursionCount; | |
| 200 return true; | |
| 201 } | |
| 202 | |
| 203 return false; | |
| 204 } | |
| 205 | |
| 206 bool RecursiveMutex::tryLock() | |
| 207 { | |
| 208 // CRITICAL_SECTION is recursive/reentrant so TryEnterCriticalSection will | |
| 209 // succeed if the current thread is already in the critical section. | |
| 210 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); | |
| 211 if (result == 0) { // We didn't get the lock. | |
| 212 return false; | |
| 213 } | 189 } |
| 214 ++m_mutex.m_recursionCount; | 190 ++m_mutex.m_recursionCount; |
| 215 return true; | 191 return true; |
| 216 } | 192 } |
| 217 | 193 |
| 218 bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
ds) | 194 return false; |
| 219 { | 195 } |
| 220 // Enter the wait state. | 196 |
| 221 DWORD res = WaitForSingleObject(m_blockLock, INFINITE); | 197 bool RecursiveMutex::tryLock() { |
| 198 // CRITICAL_SECTION is recursive/reentrant so TryEnterCriticalSection will |
| 199 // succeed if the current thread is already in the critical section. |
| 200 DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); |
| 201 if (result == 0) { // We didn't get the lock. |
| 202 return false; |
| 203 } |
| 204 ++m_mutex.m_recursionCount; |
| 205 return true; |
| 206 } |
| 207 |
| 208 bool PlatformCondition::timedWait(PlatformMutex& mutex, |
| 209 DWORD durationMilliseconds) { |
| 210 // Enter the wait state. |
| 211 DWORD res = WaitForSingleObject(m_blockLock, INFINITE); |
| 212 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); |
| 213 ++m_waitersBlocked; |
| 214 res = ReleaseSemaphore(m_blockLock, 1, 0); |
| 215 ASSERT_UNUSED(res, res); |
| 216 |
| 217 --mutex.m_recursionCount; |
| 218 LeaveCriticalSection(&mutex.m_internalMutex); |
| 219 |
| 220 // Main wait - use timeout. |
| 221 bool timedOut = |
| 222 (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT); |
| 223 |
| 224 res = WaitForSingleObject(m_unblockLock, INFINITE); |
| 225 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); |
| 226 |
| 227 int signalsLeft = m_waitersToUnblock; |
| 228 |
| 229 if (m_waitersToUnblock) { |
| 230 --m_waitersToUnblock; |
| 231 } else if (++m_waitersGone == (INT_MAX / 2)) { |
| 232 // timeout/canceled or spurious semaphore timeout or spurious wakeup |
| 233 // occured, normalize the m_waitersGone count this may occur if many |
| 234 // calls to wait with a timeout are made and no call to notify_* is made |
| 235 res = WaitForSingleObject(m_blockLock, INFINITE); |
| 222 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); | 236 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); |
| 223 ++m_waitersBlocked; | 237 m_waitersBlocked -= m_waitersGone; |
| 224 res = ReleaseSemaphore(m_blockLock, 1, 0); | 238 res = ReleaseSemaphore(m_blockLock, 1, 0); |
| 225 ASSERT_UNUSED(res, res); | 239 ASSERT_UNUSED(res, res); |
| 226 | 240 m_waitersGone = 0; |
| 227 --mutex.m_recursionCount; | 241 } |
| 228 LeaveCriticalSection(&mutex.m_internalMutex); | 242 |
| 229 | 243 res = ReleaseMutex(m_unblockLock); |
| 230 // Main wait - use timeout. | 244 ASSERT_UNUSED(res, res); |
| 231 bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) ==
WAIT_TIMEOUT); | 245 |
| 232 | 246 if (signalsLeft == 1) { |
| 233 res = WaitForSingleObject(m_unblockLock, INFINITE); | 247 res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. |
| 248 ASSERT_UNUSED(res, res); |
| 249 } |
| 250 |
| 251 EnterCriticalSection(&mutex.m_internalMutex); |
| 252 ++mutex.m_recursionCount; |
| 253 |
| 254 return !timedOut; |
| 255 } |
| 256 |
| 257 void PlatformCondition::signal(bool unblockAll) { |
| 258 unsigned signalsToIssue = 0; |
| 259 |
| 260 DWORD res = WaitForSingleObject(m_unblockLock, INFINITE); |
| 261 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); |
| 262 |
| 263 if (m_waitersToUnblock) { // the gate is already closed |
| 264 if (!m_waitersBlocked) { // no-op |
| 265 res = ReleaseMutex(m_unblockLock); |
| 266 ASSERT_UNUSED(res, res); |
| 267 return; |
| 268 } |
| 269 |
| 270 if (unblockAll) { |
| 271 signalsToIssue = m_waitersBlocked; |
| 272 m_waitersToUnblock += m_waitersBlocked; |
| 273 m_waitersBlocked = 0; |
| 274 } else { |
| 275 signalsToIssue = 1; |
| 276 ++m_waitersToUnblock; |
| 277 --m_waitersBlocked; |
| 278 } |
| 279 } else if (m_waitersBlocked > m_waitersGone) { |
| 280 res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate. |
| 234 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); | 281 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); |
| 235 | 282 if (m_waitersGone != 0) { |
| 236 int signalsLeft = m_waitersToUnblock; | 283 m_waitersBlocked -= m_waitersGone; |
| 237 | 284 m_waitersGone = 0; |
| 238 if (m_waitersToUnblock) { | 285 } |
| 239 --m_waitersToUnblock; | 286 if (unblockAll) { |
| 240 } else if (++m_waitersGone == (INT_MAX / 2)) { | 287 signalsToIssue = m_waitersBlocked; |
| 241 // timeout/canceled or spurious semaphore timeout or spurious wakeup | 288 m_waitersToUnblock = m_waitersBlocked; |
| 242 // occured, normalize the m_waitersGone count this may occur if many | 289 m_waitersBlocked = 0; |
| 243 // calls to wait with a timeout are made and no call to notify_* is made | 290 } else { |
| 244 res = WaitForSingleObject(m_blockLock, INFINITE); | 291 signalsToIssue = 1; |
| 245 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); | 292 m_waitersToUnblock = 1; |
| 246 m_waitersBlocked -= m_waitersGone; | 293 --m_waitersBlocked; |
| 247 res = ReleaseSemaphore(m_blockLock, 1, 0); | 294 } |
| 248 ASSERT_UNUSED(res, res); | 295 } else { // No-op. |
| 249 m_waitersGone = 0; | |
| 250 } | |
| 251 | |
| 252 res = ReleaseMutex(m_unblockLock); | 296 res = ReleaseMutex(m_unblockLock); |
| 253 ASSERT_UNUSED(res, res); | 297 ASSERT_UNUSED(res, res); |
| 254 | 298 return; |
| 255 if (signalsLeft == 1) { | 299 } |
| 256 res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. | 300 |
| 257 ASSERT_UNUSED(res, res); | 301 res = ReleaseMutex(m_unblockLock); |
| 258 } | 302 ASSERT_UNUSED(res, res); |
| 259 | 303 |
| 260 EnterCriticalSection(&mutex.m_internalMutex); | 304 if (signalsToIssue) { |
| 261 ++mutex.m_recursionCount; | 305 res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0); |
| 262 | 306 ASSERT_UNUSED(res, res); |
| 263 return !timedOut; | 307 } |
| 264 } | |
| 265 | |
| 266 void PlatformCondition::signal(bool unblockAll) | |
| 267 { | |
| 268 unsigned signalsToIssue = 0; | |
| 269 | |
| 270 DWORD res = WaitForSingleObject(m_unblockLock, INFINITE); | |
| 271 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); | |
| 272 | |
| 273 if (m_waitersToUnblock) { // the gate is already closed | |
| 274 if (!m_waitersBlocked) { // no-op | |
| 275 res = ReleaseMutex(m_unblockLock); | |
| 276 ASSERT_UNUSED(res, res); | |
| 277 return; | |
| 278 } | |
| 279 | |
| 280 if (unblockAll) { | |
| 281 signalsToIssue = m_waitersBlocked; | |
| 282 m_waitersToUnblock += m_waitersBlocked; | |
| 283 m_waitersBlocked = 0; | |
| 284 } else { | |
| 285 signalsToIssue = 1; | |
| 286 ++m_waitersToUnblock; | |
| 287 --m_waitersBlocked; | |
| 288 } | |
| 289 } else if (m_waitersBlocked > m_waitersGone) { | |
| 290 res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate. | |
| 291 ASSERT_UNUSED(res, res == WAIT_OBJECT_0); | |
| 292 if (m_waitersGone != 0) { | |
| 293 m_waitersBlocked -= m_waitersGone; | |
| 294 m_waitersGone = 0; | |
| 295 } | |
| 296 if (unblockAll) { | |
| 297 signalsToIssue = m_waitersBlocked; | |
| 298 m_waitersToUnblock = m_waitersBlocked; | |
| 299 m_waitersBlocked = 0; | |
| 300 } else { | |
| 301 signalsToIssue = 1; | |
| 302 m_waitersToUnblock = 1; | |
| 303 --m_waitersBlocked; | |
| 304 } | |
| 305 } else { // No-op. | |
| 306 res = ReleaseMutex(m_unblockLock); | |
| 307 ASSERT_UNUSED(res, res); | |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 res = ReleaseMutex(m_unblockLock); | |
| 312 ASSERT_UNUSED(res, res); | |
| 313 | |
| 314 if (signalsToIssue) { | |
| 315 res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0); | |
| 316 ASSERT_UNUSED(res, res); | |
| 317 } | |
| 318 } | 308 } |
| 319 | 309 |
| 320 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); | 310 static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); |
| 321 | 311 |
| 322 ThreadCondition::ThreadCondition() | 312 ThreadCondition::ThreadCondition() { |
| 323 { | 313 m_condition.m_waitersGone = 0; |
| 324 m_condition.m_waitersGone = 0; | 314 m_condition.m_waitersBlocked = 0; |
| 325 m_condition.m_waitersBlocked = 0; | 315 m_condition.m_waitersToUnblock = 0; |
| 326 m_condition.m_waitersToUnblock = 0; | 316 m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0); |
| 327 m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0); | 317 m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0); |
| 328 m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0); | 318 m_condition.m_unblockLock = CreateMutex(0, 0, 0); |
| 329 m_condition.m_unblockLock = CreateMutex(0, 0, 0); | 319 |
| 330 | 320 if (!m_condition.m_blockLock || !m_condition.m_blockQueue || |
| 331 if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_
unblockLock) { | 321 !m_condition.m_unblockLock) { |
| 332 if (m_condition.m_blockLock) | 322 if (m_condition.m_blockLock) |
| 333 CloseHandle(m_condition.m_blockLock); | 323 CloseHandle(m_condition.m_blockLock); |
| 334 if (m_condition.m_blockQueue) | 324 if (m_condition.m_blockQueue) |
| 335 CloseHandle(m_condition.m_blockQueue); | 325 CloseHandle(m_condition.m_blockQueue); |
| 336 if (m_condition.m_unblockLock) | 326 if (m_condition.m_unblockLock) |
| 337 CloseHandle(m_condition.m_unblockLock); | 327 CloseHandle(m_condition.m_unblockLock); |
| 338 } | 328 } |
| 339 } | 329 } |
| 340 | 330 |
| 341 ThreadCondition::~ThreadCondition() | 331 ThreadCondition::~ThreadCondition() { |
| 342 { | 332 CloseHandle(m_condition.m_blockLock); |
| 343 CloseHandle(m_condition.m_blockLock); | 333 CloseHandle(m_condition.m_blockQueue); |
| 344 CloseHandle(m_condition.m_blockQueue); | 334 CloseHandle(m_condition.m_unblockLock); |
| 345 CloseHandle(m_condition.m_unblockLock); | 335 } |
| 346 } | 336 |
| 347 | 337 void ThreadCondition::wait(MutexBase& mutex) { |
| 348 void ThreadCondition::wait(MutexBase& mutex) | 338 m_condition.timedWait(mutex.impl(), INFINITE); |
| 349 { | 339 } |
| 350 m_condition.timedWait(mutex.impl(), INFINITE); | 340 |
| 351 } | 341 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime) { |
| 352 | 342 DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); |
| 353 bool ThreadCondition::timedWait(MutexBase& mutex, double absoluteTime) | 343 |
| 354 { | 344 if (!interval) { |
| 355 DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); | 345 // Consider the wait to have timed out, even if our condition has already be
en signaled, to |
| 356 | 346 // match the pthreads implementation. |
| 357 if (!interval) { | 347 return false; |
| 358 // Consider the wait to have timed out, even if our condition has alread
y been signaled, to | 348 } |
| 359 // match the pthreads implementation. | 349 |
| 360 return false; | 350 return m_condition.timedWait(mutex.impl(), interval); |
| 361 } | 351 } |
| 362 | 352 |
| 363 return m_condition.timedWait(mutex.impl(), interval); | 353 void ThreadCondition::signal() { |
| 364 } | 354 m_condition.signal(false); // Unblock only 1 thread. |
| 365 | 355 } |
| 366 void ThreadCondition::signal() | 356 |
| 367 { | 357 void ThreadCondition::broadcast() { |
| 368 m_condition.signal(false); // Unblock only 1 thread. | 358 m_condition.signal(true); // Unblock all threads. |
| 369 } | 359 } |
| 370 | 360 |
| 371 void ThreadCondition::broadcast() | 361 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) { |
| 372 { | 362 double currentTime = WTF::currentTime(); |
| 373 m_condition.signal(true); // Unblock all threads. | 363 |
| 374 } | 364 // Time is in the past - return immediately. |
| 375 | 365 if (absoluteTime < currentTime) |
| 376 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) | 366 return 0; |
| 377 { | 367 |
| 378 double currentTime = WTF::currentTime(); | 368 // Time is too far in the future (and would overflow unsigned long) - wait for
ever. |
| 379 | 369 if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) |
| 380 // Time is in the past - return immediately. | 370 return INFINITE; |
| 381 if (absoluteTime < currentTime) | 371 |
| 382 return 0; | 372 return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0); |
| 383 | |
| 384 // Time is too far in the future (and would overflow unsigned long) - wait f
orever. | |
| 385 if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) | |
| 386 return INFINITE; | |
| 387 | |
| 388 return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0); | |
| 389 } | 373 } |
| 390 | 374 |
| 391 #if ENABLE(ASSERT) | 375 #if ENABLE(ASSERT) |
| 392 static bool s_threadCreated = false; | 376 static bool s_threadCreated = false; |
| 393 | 377 |
| 394 bool isAtomicallyInitializedStaticMutexLockHeld() | 378 bool isAtomicallyInitializedStaticMutexLockHeld() { |
| 395 { | 379 return atomicallyInitializedStaticMutex && |
| 396 return atomicallyInitializedStaticMutex && atomicallyInitializedStaticMutex-
>locked(); | 380 atomicallyInitializedStaticMutex->locked(); |
| 397 } | 381 } |
| 398 | 382 |
| 399 bool isBeforeThreadCreated() | 383 bool isBeforeThreadCreated() { |
| 400 { | 384 return !s_threadCreated; |
| 401 return !s_threadCreated; | 385 } |
| 402 } | 386 |
| 403 | 387 void willCreateThread() { |
| 404 void willCreateThread() | 388 s_threadCreated = true; |
| 405 { | |
| 406 s_threadCreated = true; | |
| 407 } | 389 } |
| 408 #endif | 390 #endif |
| 409 | 391 |
| 410 } // namespace WTF | 392 } // namespace WTF |
| 411 | 393 |
| 412 #endif // OS(WIN) | 394 #endif // OS(WIN) |
| OLD | NEW |