OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
7 | 7 |
8 #include "bin/eventhandler.h" | 8 #include "bin/eventhandler.h" |
9 #include "bin/eventhandler_win.h" | 9 #include "bin/eventhandler_win.h" |
10 | 10 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 | 114 |
115 Handle::Handle(intptr_t handle) | 115 Handle::Handle(intptr_t handle) |
116 : DescriptorInfoBase(handle), | 116 : DescriptorInfoBase(handle), |
117 handle_(reinterpret_cast<HANDLE>(handle)), | 117 handle_(reinterpret_cast<HANDLE>(handle)), |
118 completion_port_(INVALID_HANDLE_VALUE), | 118 completion_port_(INVALID_HANDLE_VALUE), |
119 event_handler_(NULL), | 119 event_handler_(NULL), |
120 data_ready_(NULL), | 120 data_ready_(NULL), |
121 pending_read_(NULL), | 121 pending_read_(NULL), |
122 pending_write_(NULL), | 122 pending_write_(NULL), |
123 last_error_(NOERROR), | 123 last_error_(NOERROR), |
124 flags_(0) { | 124 flags_(0), |
125 read_thread_id_(Thread::kInvalidThreadId), | |
126 read_thread_running_(false), | |
127 read_thread_finished_(false), | |
128 read_thread_monitor_(new Monitor()) { | |
Ivan Posva
2015/08/25 22:21:03
Can we share the monitor and the critical section?
| |
125 InitializeCriticalSection(&cs_); | 129 InitializeCriticalSection(&cs_); |
126 } | 130 } |
127 | 131 |
128 | 132 |
129 Handle::~Handle() { | 133 Handle::~Handle() { |
134 delete read_thread_monitor_; | |
130 DeleteCriticalSection(&cs_); | 135 DeleteCriticalSection(&cs_); |
131 } | 136 } |
132 | 137 |
133 | 138 |
134 void Handle::Lock() { | 139 void Handle::Lock() { |
135 EnterCriticalSection(&cs_); | 140 EnterCriticalSection(&cs_); |
136 } | 141 } |
137 | 142 |
138 | 143 |
139 void Handle::Unlock() { | 144 void Handle::Unlock() { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 return pending_read_ != NULL; | 184 return pending_read_ != NULL; |
180 } | 185 } |
181 | 186 |
182 | 187 |
183 bool Handle::HasPendingWrite() { | 188 bool Handle::HasPendingWrite() { |
184 ScopedLock lock(this); | 189 ScopedLock lock(this); |
185 return pending_write_ != NULL; | 190 return pending_write_ != NULL; |
186 } | 191 } |
187 | 192 |
188 | 193 |
194 void Handle::NotifyReadThreadFinished() { | |
195 MonitorLocker ml(read_thread_monitor_); | |
196 read_thread_finished_ = true; | |
Ivan Posva
2015/08/25 22:21:03
Assertions?
zra
2015/08/26 05:24:39
Done.
| |
197 ml.Notify(); | |
198 } | |
199 | |
200 | |
201 void Handle::WaitForReadThreadFinished() { | |
202 // Join the Reader thread if there is one. | |
203 ThreadId to_join = Thread::kInvalidThreadId; | |
204 { | |
205 MonitorLocker ml(read_thread_monitor_); | |
206 if (read_thread_id_ != Thread::kInvalidThreadId) { | |
207 while (!read_thread_finished_) { | |
208 ml.Wait(); | |
209 } | |
210 read_thread_finished_ = false; | |
211 read_thread_running_ = false; | |
212 to_join = read_thread_id_; | |
213 read_thread_id_ = Thread::kInvalidThreadId; | |
214 } | |
215 } | |
216 if (to_join != Thread::kInvalidThreadId) { | |
217 Thread::Join(to_join); | |
218 } | |
219 } | |
220 | |
221 | |
189 void Handle::ReadComplete(OverlappedBuffer* buffer) { | 222 void Handle::ReadComplete(OverlappedBuffer* buffer) { |
190 ScopedLock lock(this); | 223 ScopedLock lock(this); |
191 // Currently only one outstanding read at the time. | 224 // Currently only one outstanding read at the time. |
192 ASSERT(pending_read_ == buffer); | 225 ASSERT(pending_read_ == buffer); |
193 ASSERT(data_ready_ == NULL); | 226 ASSERT(data_ready_ == NULL); |
194 if (!IsClosing() && !buffer->IsEmpty()) { | 227 if (!IsClosing() && !buffer->IsEmpty()) { |
195 data_ready_ = pending_read_; | 228 data_ready_ = pending_read_; |
196 } else { | 229 } else { |
197 OverlappedBuffer::DisposeBuffer(buffer); | 230 OverlappedBuffer::DisposeBuffer(buffer); |
198 } | 231 } |
199 pending_read_ = NULL; | 232 pending_read_ = NULL; |
233 WaitForReadThreadFinished(); | |
200 } | 234 } |
201 | 235 |
202 | 236 |
203 void Handle::RecvFromComplete(OverlappedBuffer* buffer) { | 237 void Handle::RecvFromComplete(OverlappedBuffer* buffer) { |
204 ReadComplete(buffer); | 238 ReadComplete(buffer); |
205 } | 239 } |
206 | 240 |
207 | 241 |
208 void Handle::WriteComplete(OverlappedBuffer* buffer) { | 242 void Handle::WriteComplete(OverlappedBuffer* buffer) { |
209 ScopedLock lock(this); | 243 ScopedLock lock(this); |
210 // Currently only one outstanding write at the time. | 244 // Currently only one outstanding write at the time. |
211 ASSERT(pending_write_ == buffer); | 245 ASSERT(pending_write_ == buffer); |
212 OverlappedBuffer::DisposeBuffer(buffer); | 246 OverlappedBuffer::DisposeBuffer(buffer); |
213 pending_write_ = NULL; | 247 pending_write_ = NULL; |
214 } | 248 } |
215 | 249 |
216 | 250 |
217 static void ReadFileThread(uword args) { | 251 static void ReadFileThread(uword args) { |
218 Handle* handle = reinterpret_cast<Handle*>(args); | 252 Handle* handle = reinterpret_cast<Handle*>(args); |
219 handle->ReadSyncCompleteAsync(); | 253 handle->ReadSyncCompleteAsync(); |
220 } | 254 } |
221 | 255 |
222 | 256 |
257 void Handle::NotifyReadThreadStarted() { | |
258 MonitorLocker ml(read_thread_monitor_); | |
259 read_thread_id_ = Thread::GetCurrentThreadId(); | |
260 read_thread_running_ = true; | |
261 ml.Notify(); | |
262 } | |
263 | |
264 | |
265 void Handle::WaitForReadThreadStarted() { | |
266 MonitorLocker ml(read_thread_monitor_); | |
267 while (!read_thread_running_) { | |
268 ml.Wait(); | |
269 } | |
270 ASSERT(read_thread_id_ != Thread::kInvalidThreadId); | |
271 } | |
272 | |
273 | |
223 void Handle::ReadSyncCompleteAsync() { | 274 void Handle::ReadSyncCompleteAsync() { |
275 NotifyReadThreadStarted(); | |
224 ASSERT(pending_read_ != NULL); | 276 ASSERT(pending_read_ != NULL); |
225 ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize); | 277 ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize); |
226 | 278 |
227 DWORD buffer_size = pending_read_->GetBufferSize(); | 279 DWORD buffer_size = pending_read_->GetBufferSize(); |
228 if (GetFileType(handle_) == FILE_TYPE_CHAR) { | 280 if (GetFileType(handle_) == FILE_TYPE_CHAR) { |
229 buffer_size = kStdOverlappedBufferSize; | 281 buffer_size = kStdOverlappedBufferSize; |
230 } | 282 } |
231 DWORD bytes_read = 0; | 283 DWORD bytes_read = 0; |
232 BOOL ok = ReadFile(handle_, | 284 BOOL ok = ReadFile(handle_, |
233 pending_read_->GetBufferStart(), | 285 pending_read_->GetBufferStart(), |
234 buffer_size, | 286 buffer_size, |
235 &bytes_read, | 287 &bytes_read, |
236 NULL); | 288 NULL); |
237 if (!ok) { | 289 if (!ok) { |
238 bytes_read = 0; | 290 bytes_read = 0; |
239 } | 291 } |
240 OVERLAPPED* overlapped = pending_read_->GetCleanOverlapped(); | 292 OVERLAPPED* overlapped = pending_read_->GetCleanOverlapped(); |
241 ok = PostQueuedCompletionStatus(event_handler_->completion_port(), | 293 ok = PostQueuedCompletionStatus(event_handler_->completion_port(), |
242 bytes_read, | 294 bytes_read, |
243 reinterpret_cast<ULONG_PTR>(this), | 295 reinterpret_cast<ULONG_PTR>(this), |
244 overlapped); | 296 overlapped); |
245 if (!ok) { | 297 if (!ok) { |
246 FATAL("PostQueuedCompletionStatus failed"); | 298 FATAL("PostQueuedCompletionStatus failed"); |
247 } | 299 } |
300 NotifyReadThreadFinished(); | |
248 } | 301 } |
249 | 302 |
250 | 303 |
251 bool Handle::IssueRead() { | 304 bool Handle::IssueRead() { |
252 ScopedLock lock(this); | 305 ScopedLock lock(this); |
253 ASSERT(type_ != kListenSocket); | 306 ASSERT(type_ != kListenSocket); |
254 ASSERT(pending_read_ == NULL); | 307 ASSERT(pending_read_ == NULL); |
255 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); | 308 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); |
256 if (SupportsOverlappedIO()) { | 309 if (SupportsOverlappedIO()) { |
257 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); | 310 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); |
(...skipping 12 matching lines...) Expand all Loading... | |
270 HandleIssueError(); | 323 HandleIssueError(); |
271 return false; | 324 return false; |
272 } else { | 325 } else { |
273 // Completing asynchronously through thread. | 326 // Completing asynchronously through thread. |
274 pending_read_ = buffer; | 327 pending_read_ = buffer; |
275 int result = Thread::Start(ReadFileThread, | 328 int result = Thread::Start(ReadFileThread, |
276 reinterpret_cast<uword>(this)); | 329 reinterpret_cast<uword>(this)); |
277 if (result != 0) { | 330 if (result != 0) { |
278 FATAL1("Failed to start read file thread %d", result); | 331 FATAL1("Failed to start read file thread %d", result); |
279 } | 332 } |
333 WaitForReadThreadStarted(); | |
280 return true; | 334 return true; |
281 } | 335 } |
282 } | 336 } |
283 | 337 |
284 | 338 |
285 bool Handle::IssueRecvFrom() { | 339 bool Handle::IssueRecvFrom() { |
286 return false; | 340 return false; |
287 } | 341 } |
288 | 342 |
289 | 343 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
670 | 724 |
671 static void WriteFileThread(uword args) { | 725 static void WriteFileThread(uword args) { |
672 StdHandle* handle = reinterpret_cast<StdHandle*>(args); | 726 StdHandle* handle = reinterpret_cast<StdHandle*>(args); |
673 handle->RunWriteLoop(); | 727 handle->RunWriteLoop(); |
674 } | 728 } |
675 | 729 |
676 | 730 |
677 void StdHandle::RunWriteLoop() { | 731 void StdHandle::RunWriteLoop() { |
678 write_monitor_->Enter(); | 732 write_monitor_->Enter(); |
679 write_thread_running_ = true; | 733 write_thread_running_ = true; |
734 thread_id_ = Thread::GetCurrentThreadId(); | |
680 // Notify we have started. | 735 // Notify we have started. |
681 write_monitor_->Notify(); | 736 write_monitor_->Notify(); |
682 | 737 |
683 while (write_thread_running_) { | 738 while (write_thread_running_) { |
684 write_monitor_->Wait(Monitor::kNoTimeout); | 739 write_monitor_->Wait(Monitor::kNoTimeout); |
685 if (pending_write_ != NULL) { | 740 if (pending_write_ != NULL) { |
686 // We woke up and had a pending write. Execute it. | 741 // We woke up and had a pending write. Execute it. |
687 WriteSyncCompleteAsync(); | 742 WriteSyncCompleteAsync(); |
688 } | 743 } |
689 } | 744 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
755 | 810 |
756 | 811 |
757 void StdHandle::DoClose() { | 812 void StdHandle::DoClose() { |
758 MonitorLocker locker(write_monitor_); | 813 MonitorLocker locker(write_monitor_); |
759 if (write_thread_exists_) { | 814 if (write_thread_exists_) { |
760 write_thread_running_ = false; | 815 write_thread_running_ = false; |
761 locker.Notify(); | 816 locker.Notify(); |
762 while (write_thread_exists_) { | 817 while (write_thread_exists_) { |
763 locker.Wait(Monitor::kNoTimeout); | 818 locker.Wait(Monitor::kNoTimeout); |
764 } | 819 } |
820 Thread::Join(thread_id_); | |
765 } | 821 } |
766 Handle::DoClose(); | 822 Handle::DoClose(); |
767 } | 823 } |
768 | 824 |
769 | 825 |
770 bool ClientSocket::LoadDisconnectEx() { | 826 bool ClientSocket::LoadDisconnectEx() { |
771 // Load the DisconnectEx function into memory using WSAIoctl. | 827 // Load the DisconnectEx function into memory using WSAIoctl. |
772 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; | 828 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; |
773 DWORD bytes; | 829 DWORD bytes; |
774 int status = WSAIoctl(socket(), | 830 int status = WSAIoctl(socket(), |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1271 HandleConnect(client_socket, bytes, buffer); | 1327 HandleConnect(client_socket, bytes, buffer); |
1272 break; | 1328 break; |
1273 } | 1329 } |
1274 default: | 1330 default: |
1275 UNREACHABLE(); | 1331 UNREACHABLE(); |
1276 } | 1332 } |
1277 } | 1333 } |
1278 | 1334 |
1279 | 1335 |
1280 EventHandlerImplementation::EventHandlerImplementation() { | 1336 EventHandlerImplementation::EventHandlerImplementation() { |
1337 startup_monitor_ = new Monitor(); | |
1338 handler_thread_id_ = Thread::kInvalidThreadId; | |
1281 completion_port_ = | 1339 completion_port_ = |
1282 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); | 1340 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); |
1283 if (completion_port_ == NULL) { | 1341 if (completion_port_ == NULL) { |
1284 FATAL("Completion port creation failed"); | 1342 FATAL("Completion port creation failed"); |
1285 } | 1343 } |
1286 shutdown_ = false; | 1344 shutdown_ = false; |
1287 } | 1345 } |
1288 | 1346 |
1289 | 1347 |
1290 EventHandlerImplementation::~EventHandlerImplementation() { | 1348 EventHandlerImplementation::~EventHandlerImplementation() { |
1349 Thread::Join(handler_thread_id_); | |
1350 delete startup_monitor_; | |
1291 CloseHandle(completion_port_); | 1351 CloseHandle(completion_port_); |
1292 } | 1352 } |
1293 | 1353 |
1294 | 1354 |
1295 int64_t EventHandlerImplementation::GetTimeout() { | 1355 int64_t EventHandlerImplementation::GetTimeout() { |
1296 if (!timeout_queue_.HasTimeout()) { | 1356 if (!timeout_queue_.HasTimeout()) { |
1297 return kInfinityTimeout; | 1357 return kInfinityTimeout; |
1298 } | 1358 } |
1299 int64_t millis = timeout_queue_.CurrentTimeout() - | 1359 int64_t millis = timeout_queue_.CurrentTimeout() - |
1300 TimerUtils::GetCurrentTimeMilliseconds(); | 1360 TimerUtils::GetCurrentTimeMilliseconds(); |
(...skipping 14 matching lines...) Expand all Loading... | |
1315 FATAL("PostQueuedCompletionStatus failed"); | 1375 FATAL("PostQueuedCompletionStatus failed"); |
1316 } | 1376 } |
1317 } | 1377 } |
1318 | 1378 |
1319 | 1379 |
1320 void EventHandlerImplementation::EventHandlerEntry(uword args) { | 1380 void EventHandlerImplementation::EventHandlerEntry(uword args) { |
1321 EventHandler* handler = reinterpret_cast<EventHandler*>(args); | 1381 EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
1322 EventHandlerImplementation* handler_impl = &handler->delegate_; | 1382 EventHandlerImplementation* handler_impl = &handler->delegate_; |
1323 ASSERT(handler_impl != NULL); | 1383 ASSERT(handler_impl != NULL); |
1324 | 1384 |
1385 { | |
1386 MonitorLocker ml(handler_impl->startup_monitor_); | |
1387 handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId(); | |
1388 ml.Notify(); | |
1389 } | |
1390 | |
1325 while (!handler_impl->shutdown_) { | 1391 while (!handler_impl->shutdown_) { |
1326 DWORD bytes; | 1392 DWORD bytes; |
1327 ULONG_PTR key; | 1393 ULONG_PTR key; |
1328 OVERLAPPED* overlapped; | 1394 OVERLAPPED* overlapped; |
1329 int64_t millis = handler_impl->GetTimeout(); | 1395 int64_t millis = handler_impl->GetTimeout(); |
1330 ASSERT(millis == kInfinityTimeout || millis >= 0); | 1396 ASSERT(millis == kInfinityTimeout || millis >= 0); |
1331 if (millis > kMaxInt32) millis = kMaxInt32; | 1397 if (millis > kMaxInt32) millis = kMaxInt32; |
1332 ASSERT(sizeof(int32_t) == sizeof(DWORD)); | 1398 ASSERT(sizeof(int32_t) == sizeof(DWORD)); |
1333 BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(), | 1399 BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(), |
1334 &bytes, | 1400 &bytes, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1375 } | 1441 } |
1376 | 1442 |
1377 | 1443 |
1378 void EventHandlerImplementation::Start(EventHandler* handler) { | 1444 void EventHandlerImplementation::Start(EventHandler* handler) { |
1379 int result = Thread::Start(EventHandlerEntry, | 1445 int result = Thread::Start(EventHandlerEntry, |
1380 reinterpret_cast<uword>(handler)); | 1446 reinterpret_cast<uword>(handler)); |
1381 if (result != 0) { | 1447 if (result != 0) { |
1382 FATAL1("Failed to start event handler thread %d", result); | 1448 FATAL1("Failed to start event handler thread %d", result); |
1383 } | 1449 } |
1384 | 1450 |
1451 { | |
1452 MonitorLocker ml(startup_monitor_); | |
1453 while (handler_thread_id_ == Thread::kInvalidThreadId) { | |
1454 ml.Wait(); | |
1455 } | |
1456 } | |
1457 | |
1385 // Initialize Winsock32 | 1458 // Initialize Winsock32 |
1386 if (!Socket::Initialize()) { | 1459 if (!Socket::Initialize()) { |
1387 FATAL("Failed to initialized Windows sockets"); | 1460 FATAL("Failed to initialized Windows sockets"); |
1388 } | 1461 } |
1389 } | 1462 } |
1390 | 1463 |
1391 | 1464 |
1392 void EventHandlerImplementation::Shutdown() { | 1465 void EventHandlerImplementation::Shutdown() { |
1393 SendData(kShutdownId, 0, 0); | 1466 SendData(kShutdownId, 0, 0); |
1394 } | 1467 } |
1395 | 1468 |
1396 } // namespace bin | 1469 } // namespace bin |
1397 } // namespace dart | 1470 } // namespace dart |
1398 | 1471 |
1399 #endif // defined(TARGET_OS_WINDOWS) | 1472 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |