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 | 9 |
10 #include <process.h> // NOLINT | 10 #include <process.h> // NOLINT |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 Handle::Handle(HANDLE handle) | 100 Handle::Handle(HANDLE handle) |
101 : handle_(reinterpret_cast<HANDLE>(handle)), | 101 : handle_(reinterpret_cast<HANDLE>(handle)), |
102 port_(0), | 102 port_(0), |
103 mask_(0), | 103 mask_(0), |
104 completion_port_(INVALID_HANDLE_VALUE), | 104 completion_port_(INVALID_HANDLE_VALUE), |
105 event_handler_(NULL), | 105 event_handler_(NULL), |
106 data_ready_(NULL), | 106 data_ready_(NULL), |
107 pending_read_(NULL), | 107 pending_read_(NULL), |
108 pending_write_(NULL), | 108 pending_write_(NULL), |
109 last_error_(NOERROR), | 109 last_error_(NOERROR), |
| 110 thread_wrote_(0), |
110 flags_(0) { | 111 flags_(0) { |
111 InitializeCriticalSection(&cs_); | 112 InitializeCriticalSection(&cs_); |
112 } | 113 } |
113 | 114 |
114 | 115 |
115 Handle::Handle(HANDLE handle, Dart_Port port) | 116 Handle::Handle(HANDLE handle, Dart_Port port) |
116 : handle_(reinterpret_cast<HANDLE>(handle)), | 117 : handle_(reinterpret_cast<HANDLE>(handle)), |
117 port_(port), | 118 port_(port), |
118 mask_(0), | 119 mask_(0), |
119 completion_port_(INVALID_HANDLE_VALUE), | 120 completion_port_(INVALID_HANDLE_VALUE), |
120 event_handler_(NULL), | 121 event_handler_(NULL), |
121 data_ready_(NULL), | 122 data_ready_(NULL), |
122 pending_read_(NULL), | 123 pending_read_(NULL), |
123 pending_write_(NULL), | 124 pending_write_(NULL), |
124 last_error_(NOERROR), | 125 last_error_(NOERROR), |
| 126 thread_wrote_(0), |
125 flags_(0) { | 127 flags_(0) { |
126 InitializeCriticalSection(&cs_); | 128 InitializeCriticalSection(&cs_); |
127 } | 129 } |
128 | 130 |
129 | 131 |
130 Handle::~Handle() { | 132 Handle::~Handle() { |
131 DeleteCriticalSection(&cs_); | 133 DeleteCriticalSection(&cs_); |
132 } | 134 } |
133 | 135 |
134 | 136 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 } | 327 } |
326 } | 328 } |
327 | 329 |
328 | 330 |
329 bool FileHandle::IsClosed() { | 331 bool FileHandle::IsClosed() { |
330 return IsClosing() && !HasPendingRead() && !HasPendingWrite(); | 332 return IsClosing() && !HasPendingRead() && !HasPendingWrite(); |
331 } | 333 } |
332 | 334 |
333 | 335 |
334 void FileHandle::DoClose() { | 336 void FileHandle::DoClose() { |
335 if (GetStdHandle(STD_OUTPUT_HANDLE) == handle_) { | 337 if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) { |
336 int fd = _open("NUL", _O_WRONLY); | 338 int fd = _open("NUL", _O_WRONLY); |
337 ASSERT(fd >= 0); | 339 ASSERT(fd >= 0); |
338 _dup2(fd, _fileno(stdout)); | 340 _dup2(fd, _fileno(stdout)); |
339 close(fd); | 341 close(fd); |
340 } else { | 342 } else { |
341 Handle::DoClose(); | 343 Handle::DoClose(); |
342 } | 344 } |
343 } | 345 } |
344 | 346 |
345 | 347 |
346 void DirectoryWatchHandle::EnsureInitialized( | 348 void DirectoryWatchHandle::EnsureInitialized( |
347 EventHandlerImplementation* event_handler) { | 349 EventHandlerImplementation* event_handler) { |
348 ScopedLock lock(this); | 350 ScopedLock lock(this); |
349 event_handler_ = event_handler; | 351 event_handler_ = event_handler; |
350 if (completion_port_ == INVALID_HANDLE_VALUE) { | 352 if (completion_port_ == INVALID_HANDLE_VALUE) { |
351 CreateCompletionPort(event_handler_->completion_port()); | 353 CreateCompletionPort(event_handler_->completion_port()); |
352 } | 354 } |
353 } | 355 } |
354 | 356 |
355 | 357 |
356 bool DirectoryWatchHandle::IsClosed() { | 358 bool DirectoryWatchHandle::IsClosed() { |
357 return IsClosing() && pending_read_ == NULL; | 359 return IsClosing() && pending_read_ == NULL; |
358 } | 360 } |
359 | 361 |
360 | 362 |
361 void DirectoryWatchHandle::DoClose() { | |
362 Handle::DoClose(); | |
363 } | |
364 | |
365 bool DirectoryWatchHandle::IssueRead() { | 363 bool DirectoryWatchHandle::IssueRead() { |
366 ScopedLock lock(this); | 364 ScopedLock lock(this); |
367 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); | 365 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); |
368 | 366 |
369 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); | 367 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); |
370 | 368 |
371 BOOL ok = ReadDirectoryChangesW(handle_, | 369 BOOL ok = ReadDirectoryChangesW(handle_, |
372 buffer->GetBufferStart(), | 370 buffer->GetBufferStart(), |
373 buffer->GetBufferSize(), | 371 buffer->GetBufferSize(), |
374 recursive_, | 372 recursive_, |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 if (data_ready_ == NULL) return 0; | 553 if (data_ready_ == NULL) return 0; |
556 num_bytes = data_ready_->Read(buffer, num_bytes); | 554 num_bytes = data_ready_->Read(buffer, num_bytes); |
557 if (data_ready_->IsEmpty()) { | 555 if (data_ready_->IsEmpty()) { |
558 OverlappedBuffer::DisposeBuffer(data_ready_); | 556 OverlappedBuffer::DisposeBuffer(data_ready_); |
559 data_ready_ = NULL; | 557 data_ready_ = NULL; |
560 } | 558 } |
561 return num_bytes; | 559 return num_bytes; |
562 } | 560 } |
563 | 561 |
564 | 562 |
| 563 static unsigned int __stdcall WriteFileThread(void* args) { |
| 564 Handle* handle = reinterpret_cast<Handle*>(args); |
| 565 handle->WriteSyncCompleteAsync(); |
| 566 return 0; |
| 567 } |
| 568 |
| 569 |
| 570 void Handle::WriteSyncCompleteAsync() { |
| 571 ASSERT(pending_write_ != NULL); |
| 572 |
| 573 DWORD bytes_written = -1; |
| 574 BOOL ok = WriteFile(handle_, |
| 575 pending_write_->GetBufferStart(), |
| 576 pending_write_->GetBufferSize(), |
| 577 &bytes_written, |
| 578 NULL); |
| 579 if (!ok) { |
| 580 if (GetLastError() != ERROR_BROKEN_PIPE) { |
| 581 Log::PrintErr("WriteFile failed %d\n", GetLastError()); |
| 582 } |
| 583 bytes_written = 0; |
| 584 } |
| 585 thread_wrote_ += bytes_written; |
| 586 OVERLAPPED* overlapped = pending_write_->GetCleanOverlapped(); |
| 587 ok = PostQueuedCompletionStatus(event_handler_->completion_port(), |
| 588 bytes_written, |
| 589 reinterpret_cast<ULONG_PTR>(this), |
| 590 overlapped); |
| 591 if (!ok) { |
| 592 FATAL("PostQueuedCompletionStatus failed"); |
| 593 } |
| 594 } |
| 595 |
| 596 |
565 int Handle::Write(const void* buffer, int num_bytes) { | 597 int Handle::Write(const void* buffer, int num_bytes) { |
566 ScopedLock lock(this); | 598 ScopedLock lock(this); |
| 599 if (pending_write_ != NULL) return 0; |
| 600 if (num_bytes > kBufferSize) num_bytes = kBufferSize; |
567 if (SupportsOverlappedIO()) { | 601 if (SupportsOverlappedIO()) { |
568 if (pending_write_ != NULL) return 0; | |
569 if (completion_port_ == INVALID_HANDLE_VALUE) return 0; | 602 if (completion_port_ == INVALID_HANDLE_VALUE) return 0; |
570 if (num_bytes > kBufferSize) num_bytes = kBufferSize; | |
571 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); | 603 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); |
572 pending_write_->Write(buffer, num_bytes); | 604 pending_write_->Write(buffer, num_bytes); |
573 if (!IssueWrite()) return -1; | 605 if (!IssueWrite()) return -1; |
574 return num_bytes; | 606 return num_bytes; |
575 } else { | 607 } else { |
576 DWORD bytes_written = -1; | 608 // In the case of stdout and stderr, OverlappedIO is not supported. |
577 BOOL ok = WriteFile(handle_, | 609 // Here we'll instead spawn a new thread for each write, to make it async. |
578 buffer, | 610 // This code is actually never exposed to the user, as stdout and stderr is |
579 num_bytes, | 611 // not available as a RawSocket, but only wrapped in a Socket. |
580 &bytes_written, | 612 // Note that we return '0', unless a thread have already completed a write. |
581 NULL); | 613 // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541. |
582 if (!ok) { | 614 if (thread_wrote_ > 0) { |
583 if (GetLastError() != ERROR_BROKEN_PIPE) { | 615 if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; |
584 Log::PrintErr("WriteFile failed: %d\n", GetLastError()); | 616 thread_wrote_ -= num_bytes; |
585 } | 617 return num_bytes; |
586 event_handler_->HandleClosed(this); | |
587 } | 618 } |
588 return bytes_written; | 619 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); |
| 620 pending_write_->Write(buffer, num_bytes); |
| 621 // Completing asynchronously through thread. |
| 622 uint32_t tid; |
| 623 uintptr_t thread_handle = |
| 624 _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid); |
| 625 if (thread_handle == -1) { |
| 626 FATAL("Failed to start write file thread"); |
| 627 } |
| 628 return 0; |
589 } | 629 } |
590 } | 630 } |
591 | 631 |
592 | 632 |
593 bool ClientSocket::LoadDisconnectEx() { | 633 bool ClientSocket::LoadDisconnectEx() { |
594 // Load the DisconnectEx function into memory using WSAIoctl. | 634 // Load the DisconnectEx function into memory using WSAIoctl. |
595 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; | 635 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; |
596 DWORD bytes; | 636 DWORD bytes; |
597 int status = WSAIoctl(socket(), | 637 int status = WSAIoctl(socket(), |
598 SIO_GET_EXTENSION_FUNCTION_POINTER, | 638 SIO_GET_EXTENSION_FUNCTION_POINTER, |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 | 1099 |
1060 | 1100 |
1061 void EventHandlerImplementation::Shutdown() { | 1101 void EventHandlerImplementation::Shutdown() { |
1062 SendData(kShutdownId, 0, 0); | 1102 SendData(kShutdownId, 0, 0); |
1063 } | 1103 } |
1064 | 1104 |
1065 } // namespace bin | 1105 } // namespace bin |
1066 } // namespace dart | 1106 } // namespace dart |
1067 | 1107 |
1068 #endif // defined(TARGET_OS_WINDOWS) | 1108 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |