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