OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(HOST_OS_WINDOWS) | 6 #if defined(HOST_OS_WINDOWS) |
7 | 7 |
8 #include "bin/thread.h" | 8 #include "bin/thread.h" |
9 #include "bin/thread_win.h" | 9 #include "bin/thread_win.h" |
10 | 10 |
(...skipping 12 matching lines...) Expand all Loading... |
23 Thread::ThreadStartFunction function() const { return function_; } | 23 Thread::ThreadStartFunction function() const { return function_; } |
24 uword parameter() const { return parameter_; } | 24 uword parameter() const { return parameter_; } |
25 | 25 |
26 private: | 26 private: |
27 Thread::ThreadStartFunction function_; | 27 Thread::ThreadStartFunction function_; |
28 uword parameter_; | 28 uword parameter_; |
29 | 29 |
30 DISALLOW_COPY_AND_ASSIGN(ThreadStartData); | 30 DISALLOW_COPY_AND_ASSIGN(ThreadStartData); |
31 }; | 31 }; |
32 | 32 |
33 | |
34 // Dispatch to the thread start function provided by the caller. This trampoline | 33 // Dispatch to the thread start function provided by the caller. This trampoline |
35 // is used to ensure that the thread is properly destroyed if the thread just | 34 // is used to ensure that the thread is properly destroyed if the thread just |
36 // exits. | 35 // exits. |
37 static unsigned int __stdcall ThreadEntry(void* data_ptr) { | 36 static unsigned int __stdcall ThreadEntry(void* data_ptr) { |
38 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr); | 37 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr); |
39 | 38 |
40 Thread::ThreadStartFunction function = data->function(); | 39 Thread::ThreadStartFunction function = data->function(); |
41 uword parameter = data->parameter(); | 40 uword parameter = data->parameter(); |
42 delete data; | 41 delete data; |
43 | 42 |
44 MonitorData::GetMonitorWaitDataForThread(); | 43 MonitorData::GetMonitorWaitDataForThread(); |
45 | 44 |
46 // Call the supplied thread start function handing it its parameters. | 45 // Call the supplied thread start function handing it its parameters. |
47 function(parameter); | 46 function(parameter); |
48 | 47 |
49 // Clean up the monitor wait data for this thread. | 48 // Clean up the monitor wait data for this thread. |
50 MonitorWaitData::ThreadExit(); | 49 MonitorWaitData::ThreadExit(); |
51 | 50 |
52 return 0; | 51 return 0; |
53 } | 52 } |
54 | 53 |
55 | |
56 int Thread::Start(ThreadStartFunction function, uword parameter) { | 54 int Thread::Start(ThreadStartFunction function, uword parameter) { |
57 ThreadStartData* start_data = new ThreadStartData(function, parameter); | 55 ThreadStartData* start_data = new ThreadStartData(function, parameter); |
58 uint32_t tid; | 56 uint32_t tid; |
59 uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(), | 57 uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(), |
60 ThreadEntry, start_data, 0, &tid); | 58 ThreadEntry, start_data, 0, &tid); |
61 if ((thread == -1L) || (thread == 0)) { | 59 if ((thread == -1L) || (thread == 0)) { |
62 #ifdef DEBUG | 60 #ifdef DEBUG |
63 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno)); | 61 fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno)); |
64 #endif | 62 #endif |
65 return errno; | 63 return errno; |
66 } | 64 } |
67 | 65 |
68 // Close the handle, so we don't leak the thread object. | 66 // Close the handle, so we don't leak the thread object. |
69 CloseHandle(reinterpret_cast<HANDLE>(thread)); | 67 CloseHandle(reinterpret_cast<HANDLE>(thread)); |
70 | 68 |
71 return 0; | 69 return 0; |
72 } | 70 } |
73 | 71 |
74 const ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES; | 72 const ThreadLocalKey Thread::kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES; |
75 const ThreadId Thread::kInvalidThreadId = 0; | 73 const ThreadId Thread::kInvalidThreadId = 0; |
76 | 74 |
77 ThreadLocalKey Thread::CreateThreadLocal() { | 75 ThreadLocalKey Thread::CreateThreadLocal() { |
78 ThreadLocalKey key = TlsAlloc(); | 76 ThreadLocalKey key = TlsAlloc(); |
79 if (key == kUnsetThreadLocalKey) { | 77 if (key == kUnsetThreadLocalKey) { |
80 FATAL1("TlsAlloc failed %d", GetLastError()); | 78 FATAL1("TlsAlloc failed %d", GetLastError()); |
81 } | 79 } |
82 return key; | 80 return key; |
83 } | 81 } |
84 | 82 |
85 | |
86 void Thread::DeleteThreadLocal(ThreadLocalKey key) { | 83 void Thread::DeleteThreadLocal(ThreadLocalKey key) { |
87 ASSERT(key != kUnsetThreadLocalKey); | 84 ASSERT(key != kUnsetThreadLocalKey); |
88 BOOL result = TlsFree(key); | 85 BOOL result = TlsFree(key); |
89 if (!result) { | 86 if (!result) { |
90 FATAL1("TlsFree failed %d", GetLastError()); | 87 FATAL1("TlsFree failed %d", GetLastError()); |
91 } | 88 } |
92 } | 89 } |
93 | 90 |
94 | |
95 intptr_t Thread::GetMaxStackSize() { | 91 intptr_t Thread::GetMaxStackSize() { |
96 const int kStackSize = (128 * kWordSize * KB); | 92 const int kStackSize = (128 * kWordSize * KB); |
97 return kStackSize; | 93 return kStackSize; |
98 } | 94 } |
99 | 95 |
100 | |
101 ThreadId Thread::GetCurrentThreadId() { | 96 ThreadId Thread::GetCurrentThreadId() { |
102 return ::GetCurrentThreadId(); | 97 return ::GetCurrentThreadId(); |
103 } | 98 } |
104 | 99 |
105 | |
106 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) { | 100 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) { |
107 ASSERT(sizeof(id) <= sizeof(intptr_t)); | 101 ASSERT(sizeof(id) <= sizeof(intptr_t)); |
108 return static_cast<intptr_t>(id); | 102 return static_cast<intptr_t>(id); |
109 } | 103 } |
110 | 104 |
111 | |
112 bool Thread::Compare(ThreadId a, ThreadId b) { | 105 bool Thread::Compare(ThreadId a, ThreadId b) { |
113 return (a == b); | 106 return (a == b); |
114 } | 107 } |
115 | 108 |
116 | |
117 void Thread::SetThreadLocal(ThreadLocalKey key, uword value) { | 109 void Thread::SetThreadLocal(ThreadLocalKey key, uword value) { |
118 ASSERT(key != kUnsetThreadLocalKey); | 110 ASSERT(key != kUnsetThreadLocalKey); |
119 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value)); | 111 BOOL result = TlsSetValue(key, reinterpret_cast<void*>(value)); |
120 if (!result) { | 112 if (!result) { |
121 FATAL1("TlsSetValue failed %d", GetLastError()); | 113 FATAL1("TlsSetValue failed %d", GetLastError()); |
122 } | 114 } |
123 } | 115 } |
124 | 116 |
125 | |
126 void Thread::InitOnce() { | 117 void Thread::InitOnce() { |
127 MonitorWaitData::monitor_wait_data_key_ = Thread::CreateThreadLocal(); | 118 MonitorWaitData::monitor_wait_data_key_ = Thread::CreateThreadLocal(); |
128 MonitorData::GetMonitorWaitDataForThread(); | 119 MonitorData::GetMonitorWaitDataForThread(); |
129 } | 120 } |
130 | 121 |
131 | |
132 Mutex::Mutex() { | 122 Mutex::Mutex() { |
133 // Allocate unnamed semaphore with initial count 1 and max count 1. | 123 // Allocate unnamed semaphore with initial count 1 and max count 1. |
134 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL); | 124 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL); |
135 if (data_.semaphore_ == NULL) { | 125 if (data_.semaphore_ == NULL) { |
136 FATAL1("Mutex allocation failed %d", GetLastError()); | 126 FATAL1("Mutex allocation failed %d", GetLastError()); |
137 } | 127 } |
138 } | 128 } |
139 | 129 |
140 | |
141 Mutex::~Mutex() { | 130 Mutex::~Mutex() { |
142 CloseHandle(data_.semaphore_); | 131 CloseHandle(data_.semaphore_); |
143 } | 132 } |
144 | 133 |
145 | |
146 void Mutex::Lock() { | 134 void Mutex::Lock() { |
147 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE); | 135 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE); |
148 if (result != WAIT_OBJECT_0) { | 136 if (result != WAIT_OBJECT_0) { |
149 FATAL1("Mutex lock failed %d", GetLastError()); | 137 FATAL1("Mutex lock failed %d", GetLastError()); |
150 } | 138 } |
151 } | 139 } |
152 | 140 |
153 | |
154 bool Mutex::TryLock() { | 141 bool Mutex::TryLock() { |
155 // Attempt to pass the semaphore but return immediately. | 142 // Attempt to pass the semaphore but return immediately. |
156 DWORD result = WaitForSingleObject(data_.semaphore_, 0); | 143 DWORD result = WaitForSingleObject(data_.semaphore_, 0); |
157 if (result == WAIT_OBJECT_0) { | 144 if (result == WAIT_OBJECT_0) { |
158 return true; | 145 return true; |
159 } | 146 } |
160 if ((result == WAIT_ABANDONED) || (result == WAIT_FAILED)) { | 147 if ((result == WAIT_ABANDONED) || (result == WAIT_FAILED)) { |
161 FATAL1("Mutex try lock failed %d", GetLastError()); | 148 FATAL1("Mutex try lock failed %d", GetLastError()); |
162 } | 149 } |
163 ASSERT(result == WAIT_TIMEOUT); | 150 ASSERT(result == WAIT_TIMEOUT); |
164 return false; | 151 return false; |
165 } | 152 } |
166 | 153 |
167 | |
168 void Mutex::Unlock() { | 154 void Mutex::Unlock() { |
169 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL); | 155 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL); |
170 if (result == 0) { | 156 if (result == 0) { |
171 FATAL1("Mutex unlock failed %d", GetLastError()); | 157 FATAL1("Mutex unlock failed %d", GetLastError()); |
172 } | 158 } |
173 } | 159 } |
174 | 160 |
175 | |
176 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = | 161 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = |
177 Thread::kUnsetThreadLocalKey; | 162 Thread::kUnsetThreadLocalKey; |
178 | 163 |
179 | |
180 Monitor::Monitor() { | 164 Monitor::Monitor() { |
181 InitializeCriticalSection(&data_.cs_); | 165 InitializeCriticalSection(&data_.cs_); |
182 InitializeCriticalSection(&data_.waiters_cs_); | 166 InitializeCriticalSection(&data_.waiters_cs_); |
183 data_.waiters_head_ = NULL; | 167 data_.waiters_head_ = NULL; |
184 data_.waiters_tail_ = NULL; | 168 data_.waiters_tail_ = NULL; |
185 } | 169 } |
186 | 170 |
187 | |
188 Monitor::~Monitor() { | 171 Monitor::~Monitor() { |
189 DeleteCriticalSection(&data_.cs_); | 172 DeleteCriticalSection(&data_.cs_); |
190 DeleteCriticalSection(&data_.waiters_cs_); | 173 DeleteCriticalSection(&data_.waiters_cs_); |
191 } | 174 } |
192 | 175 |
193 | |
194 void Monitor::Enter() { | 176 void Monitor::Enter() { |
195 EnterCriticalSection(&data_.cs_); | 177 EnterCriticalSection(&data_.cs_); |
196 } | 178 } |
197 | 179 |
198 | |
199 void Monitor::Exit() { | 180 void Monitor::Exit() { |
200 LeaveCriticalSection(&data_.cs_); | 181 LeaveCriticalSection(&data_.cs_); |
201 } | 182 } |
202 | 183 |
203 | |
204 void MonitorWaitData::ThreadExit() { | 184 void MonitorWaitData::ThreadExit() { |
205 if (MonitorWaitData::monitor_wait_data_key_ != Thread::kUnsetThreadLocalKey) { | 185 if (MonitorWaitData::monitor_wait_data_key_ != Thread::kUnsetThreadLocalKey) { |
206 uword raw_wait_data = | 186 uword raw_wait_data = |
207 Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); | 187 Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); |
208 if (raw_wait_data != 0) { | 188 if (raw_wait_data != 0) { |
209 MonitorWaitData* wait_data = | 189 MonitorWaitData* wait_data = |
210 reinterpret_cast<MonitorWaitData*>(raw_wait_data); | 190 reinterpret_cast<MonitorWaitData*>(raw_wait_data); |
211 delete wait_data; | 191 delete wait_data; |
212 } | 192 } |
213 } | 193 } |
214 } | 194 } |
215 | 195 |
216 | |
217 void MonitorData::AddWaiter(MonitorWaitData* wait_data) { | 196 void MonitorData::AddWaiter(MonitorWaitData* wait_data) { |
218 // Add the MonitorWaitData object to the list of objects waiting for | 197 // Add the MonitorWaitData object to the list of objects waiting for |
219 // this monitor. | 198 // this monitor. |
220 EnterCriticalSection(&waiters_cs_); | 199 EnterCriticalSection(&waiters_cs_); |
221 if (waiters_tail_ == NULL) { | 200 if (waiters_tail_ == NULL) { |
222 ASSERT(waiters_head_ == NULL); | 201 ASSERT(waiters_head_ == NULL); |
223 waiters_head_ = wait_data; | 202 waiters_head_ = wait_data; |
224 waiters_tail_ = wait_data; | 203 waiters_tail_ = wait_data; |
225 } else { | 204 } else { |
226 waiters_tail_->next_ = wait_data; | 205 waiters_tail_->next_ = wait_data; |
227 waiters_tail_ = wait_data; | 206 waiters_tail_ = wait_data; |
228 } | 207 } |
229 LeaveCriticalSection(&waiters_cs_); | 208 LeaveCriticalSection(&waiters_cs_); |
230 } | 209 } |
231 | 210 |
232 | |
233 void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) { | 211 void MonitorData::RemoveWaiter(MonitorWaitData* wait_data) { |
234 // Remove the MonitorWaitData object from the list of objects | 212 // Remove the MonitorWaitData object from the list of objects |
235 // waiting for this monitor. | 213 // waiting for this monitor. |
236 EnterCriticalSection(&waiters_cs_); | 214 EnterCriticalSection(&waiters_cs_); |
237 MonitorWaitData* previous = NULL; | 215 MonitorWaitData* previous = NULL; |
238 MonitorWaitData* current = waiters_head_; | 216 MonitorWaitData* current = waiters_head_; |
239 while (current != NULL) { | 217 while (current != NULL) { |
240 if (current == wait_data) { | 218 if (current == wait_data) { |
241 if (waiters_head_ == waiters_tail_) { | 219 if (waiters_head_ == waiters_tail_) { |
242 waiters_head_ = NULL; | 220 waiters_head_ = NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
254 // Clear next. | 232 // Clear next. |
255 wait_data->next_ = NULL; | 233 wait_data->next_ = NULL; |
256 break; | 234 break; |
257 } | 235 } |
258 previous = current; | 236 previous = current; |
259 current = current->next_; | 237 current = current->next_; |
260 } | 238 } |
261 LeaveCriticalSection(&waiters_cs_); | 239 LeaveCriticalSection(&waiters_cs_); |
262 } | 240 } |
263 | 241 |
264 | |
265 void MonitorData::SignalAndRemoveFirstWaiter() { | 242 void MonitorData::SignalAndRemoveFirstWaiter() { |
266 EnterCriticalSection(&waiters_cs_); | 243 EnterCriticalSection(&waiters_cs_); |
267 MonitorWaitData* first = waiters_head_; | 244 MonitorWaitData* first = waiters_head_; |
268 if (first != NULL) { | 245 if (first != NULL) { |
269 // Remove from list. | 246 // Remove from list. |
270 if (waiters_head_ == waiters_tail_) { | 247 if (waiters_head_ == waiters_tail_) { |
271 waiters_tail_ = NULL; | 248 waiters_tail_ = NULL; |
272 waiters_head_ = NULL; | 249 waiters_head_ = NULL; |
273 } else { | 250 } else { |
274 waiters_head_ = waiters_head_->next_; | 251 waiters_head_ = waiters_head_->next_; |
275 } | 252 } |
276 // Clear next. | 253 // Clear next. |
277 first->next_ = NULL; | 254 first->next_ = NULL; |
278 // Signal event. | 255 // Signal event. |
279 BOOL result = SetEvent(first->event_); | 256 BOOL result = SetEvent(first->event_); |
280 if (result == 0) { | 257 if (result == 0) { |
281 FATAL1("Monitor::Notify failed to signal event %d", GetLastError()); | 258 FATAL1("Monitor::Notify failed to signal event %d", GetLastError()); |
282 } | 259 } |
283 } | 260 } |
284 LeaveCriticalSection(&waiters_cs_); | 261 LeaveCriticalSection(&waiters_cs_); |
285 } | 262 } |
286 | 263 |
287 | |
288 void MonitorData::SignalAndRemoveAllWaiters() { | 264 void MonitorData::SignalAndRemoveAllWaiters() { |
289 EnterCriticalSection(&waiters_cs_); | 265 EnterCriticalSection(&waiters_cs_); |
290 // Extract list to signal. | 266 // Extract list to signal. |
291 MonitorWaitData* current = waiters_head_; | 267 MonitorWaitData* current = waiters_head_; |
292 // Clear list. | 268 // Clear list. |
293 waiters_head_ = NULL; | 269 waiters_head_ = NULL; |
294 waiters_tail_ = NULL; | 270 waiters_tail_ = NULL; |
295 // Iterate and signal all events. | 271 // Iterate and signal all events. |
296 while (current != NULL) { | 272 while (current != NULL) { |
297 // Copy next. | 273 // Copy next. |
298 MonitorWaitData* next = current->next_; | 274 MonitorWaitData* next = current->next_; |
299 // Clear next. | 275 // Clear next. |
300 current->next_ = NULL; | 276 current->next_ = NULL; |
301 // Signal event. | 277 // Signal event. |
302 BOOL result = SetEvent(current->event_); | 278 BOOL result = SetEvent(current->event_); |
303 if (result == 0) { | 279 if (result == 0) { |
304 FATAL1("Failed to set event for NotifyAll %d", GetLastError()); | 280 FATAL1("Failed to set event for NotifyAll %d", GetLastError()); |
305 } | 281 } |
306 current = next; | 282 current = next; |
307 } | 283 } |
308 LeaveCriticalSection(&waiters_cs_); | 284 LeaveCriticalSection(&waiters_cs_); |
309 } | 285 } |
310 | 286 |
311 | |
312 MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() { | 287 MonitorWaitData* MonitorData::GetMonitorWaitDataForThread() { |
313 // Ensure that the thread local key for monitor wait data objects is | 288 // Ensure that the thread local key for monitor wait data objects is |
314 // initialized. | 289 // initialized. |
315 ASSERT(MonitorWaitData::monitor_wait_data_key_ != | 290 ASSERT(MonitorWaitData::monitor_wait_data_key_ != |
316 Thread::kUnsetThreadLocalKey); | 291 Thread::kUnsetThreadLocalKey); |
317 | 292 |
318 // Get the MonitorWaitData object containing the event for this | 293 // Get the MonitorWaitData object containing the event for this |
319 // thread from thread local storage. Create it if it does not exist. | 294 // thread from thread local storage. Create it if it does not exist. |
320 uword raw_wait_data = | 295 uword raw_wait_data = |
321 Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); | 296 Thread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); |
322 MonitorWaitData* wait_data = NULL; | 297 MonitorWaitData* wait_data = NULL; |
323 if (raw_wait_data == 0) { | 298 if (raw_wait_data == 0) { |
324 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); | 299 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); |
325 wait_data = new MonitorWaitData(event); | 300 wait_data = new MonitorWaitData(event); |
326 Thread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, | 301 Thread::SetThreadLocal(MonitorWaitData::monitor_wait_data_key_, |
327 reinterpret_cast<uword>(wait_data)); | 302 reinterpret_cast<uword>(wait_data)); |
328 } else { | 303 } else { |
329 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data); | 304 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data); |
330 wait_data->next_ = NULL; | 305 wait_data->next_ = NULL; |
331 } | 306 } |
332 return wait_data; | 307 return wait_data; |
333 } | 308 } |
334 | 309 |
335 | |
336 Monitor::WaitResult Monitor::Wait(int64_t millis) { | 310 Monitor::WaitResult Monitor::Wait(int64_t millis) { |
337 Monitor::WaitResult retval = kNotified; | 311 Monitor::WaitResult retval = kNotified; |
338 | 312 |
339 // Get the wait data object containing the event to wait for. | 313 // Get the wait data object containing the event to wait for. |
340 MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread(); | 314 MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread(); |
341 | 315 |
342 // Start waiting by adding the MonitorWaitData to the list of | 316 // Start waiting by adding the MonitorWaitData to the list of |
343 // waiters. | 317 // waiters. |
344 data_.AddWaiter(wait_data); | 318 data_.AddWaiter(wait_data); |
345 | 319 |
(...skipping 21 matching lines...) Expand all Loading... |
367 retval = kTimedOut; | 341 retval = kTimedOut; |
368 } | 342 } |
369 } | 343 } |
370 | 344 |
371 // Reacquire the monitor critical section before continuing. | 345 // Reacquire the monitor critical section before continuing. |
372 EnterCriticalSection(&data_.cs_); | 346 EnterCriticalSection(&data_.cs_); |
373 | 347 |
374 return retval; | 348 return retval; |
375 } | 349 } |
376 | 350 |
377 | |
378 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) { | 351 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) { |
379 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows. | 352 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows. |
380 int64_t millis = micros / kMicrosecondsPerMillisecond; | 353 int64_t millis = micros / kMicrosecondsPerMillisecond; |
381 if ((millis * kMicrosecondsPerMillisecond) < micros) { | 354 if ((millis * kMicrosecondsPerMillisecond) < micros) { |
382 // We've been asked to sleep for a fraction of a millisecond, | 355 // We've been asked to sleep for a fraction of a millisecond, |
383 // this isn't supported on Windows. Bumps milliseconds up by one | 356 // this isn't supported on Windows. Bumps milliseconds up by one |
384 // so that we never return too early. We likely return late though. | 357 // so that we never return too early. We likely return late though. |
385 millis += 1; | 358 millis += 1; |
386 } | 359 } |
387 return Wait(millis); | 360 return Wait(millis); |
388 } | 361 } |
389 | 362 |
390 | |
391 void Monitor::Notify() { | 363 void Monitor::Notify() { |
392 data_.SignalAndRemoveFirstWaiter(); | 364 data_.SignalAndRemoveFirstWaiter(); |
393 } | 365 } |
394 | 366 |
395 | |
396 void Monitor::NotifyAll() { | 367 void Monitor::NotifyAll() { |
397 // If one of the objects in the list of waiters wakes because of a | 368 // If one of the objects in the list of waiters wakes because of a |
398 // timeout before we signal it, that object will get an extra | 369 // timeout before we signal it, that object will get an extra |
399 // signal. This will be treated as a spurious wake-up and is OK | 370 // signal. This will be treated as a spurious wake-up and is OK |
400 // since all uses of monitors should recheck the condition after a | 371 // since all uses of monitors should recheck the condition after a |
401 // Wait. | 372 // Wait. |
402 data_.SignalAndRemoveAllWaiters(); | 373 data_.SignalAndRemoveAllWaiters(); |
403 } | 374 } |
404 | 375 |
405 } // namespace bin | 376 } // namespace bin |
406 } // namespace dart | 377 } // namespace dart |
407 | 378 |
408 #endif // defined(HOST_OS_WINDOWS) | 379 #endif // defined(HOST_OS_WINDOWS) |
OLD | NEW |