Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(575)

Side by Side Diff: runtime/bin/thread_win.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/bin/thread_win.h ('k') | runtime/bin/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/thread_win.h ('k') | runtime/bin/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698