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

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

Issue 25631005: Reuse thread when writing stdout/stderr on Windows. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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) 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
11 #include <winsock2.h> // NOLINT 11 #include <winsock2.h> // NOLINT
12 #include <ws2tcpip.h> // NOLINT 12 #include <ws2tcpip.h> // NOLINT
13 #include <mswsock.h> // NOLINT 13 #include <mswsock.h> // NOLINT
14 #include <io.h> // NOLINT 14 #include <io.h> // NOLINT
15 #include <fcntl.h> // NOLINT 15 #include <fcntl.h> // NOLINT
16 16
17 #include "bin/builtin.h" 17 #include "bin/builtin.h"
18 #include "bin/dartutils.h" 18 #include "bin/dartutils.h"
19 #include "bin/log.h" 19 #include "bin/log.h"
20 #include "bin/socket.h" 20 #include "bin/socket.h"
21 #include "bin/utils.h" 21 #include "bin/utils.h"
22 #include "platform/thread.h" 22 #include "platform/thread.h"
23 #include "vm/thread.h"
23 24
24 25
25 namespace dart { 26 namespace dart {
26 namespace bin { 27 namespace bin {
27 28
28 static const int kBufferSize = 64 * 1024; 29 static const int kBufferSize = 64 * 1024;
29 static const int kStdOverlappedBufferSize = 16 * 1024; 30 static const int kStdOverlappedBufferSize = 16 * 1024;
30 31
31 static const int kInfinityTimeout = -1; 32 static const int kInfinityTimeout = -1;
32 static const int kTimeoutId = -1; 33 static const int kTimeoutId = -1;
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 ScopedLock lock(this); 553 ScopedLock lock(this);
553 if (data_ready_ == NULL) return 0; 554 if (data_ready_ == NULL) return 0;
554 num_bytes = data_ready_->Read(buffer, num_bytes); 555 num_bytes = data_ready_->Read(buffer, num_bytes);
555 if (data_ready_->IsEmpty()) { 556 if (data_ready_->IsEmpty()) {
556 OverlappedBuffer::DisposeBuffer(data_ready_); 557 OverlappedBuffer::DisposeBuffer(data_ready_);
557 data_ready_ = NULL; 558 data_ready_ = NULL;
558 } 559 }
559 return num_bytes; 560 return num_bytes;
560 } 561 }
561 562
562 563
Søren Gjesse 2013/10/02 08:49:22 Please add these static variables to the Windows E
Anders Johnsen 2013/10/02 10:16:59 Done.
564 static Monitor* write_monitor = new Monitor();
565 static bool write_thread_exists = false;
566 static bool write_thread_running = false;
567 static Handle* write_handle = NULL;
568
563 static unsigned int __stdcall WriteFileThread(void* args) { 569 static unsigned int __stdcall WriteFileThread(void* args) {
564 Handle* handle = reinterpret_cast<Handle*>(args); 570 MonitorLocker locker(write_monitor);
565 handle->WriteSyncCompleteAsync(); 571 write_thread_running = true;
572 // Notify we have started.
573 locker.Notify();
574
575 while (write_thread_running) {
576 locker.Wait(Monitor::kNoTimeout);
577 if (write_handle) {
578 // We woke up and had a handle. Complete it.
579 write_handle->WriteSyncCompleteAsync();
580 write_handle = NULL;
581 }
582 }
583 write_thread_exists = false;
584 locker.Notify();
566 return 0; 585 return 0;
567 } 586 }
568 587
569 588
570 void Handle::WriteSyncCompleteAsync() { 589 void Handle::WriteSyncCompleteAsync() {
571 ASSERT(pending_write_ != NULL); 590 ASSERT(pending_write_ != NULL);
572 591
573 DWORD bytes_written = -1; 592 DWORD bytes_written = -1;
574 BOOL ok = WriteFile(handle_, 593 BOOL ok = WriteFile(handle_,
575 pending_write_->GetBufferStart(), 594 pending_write_->GetBufferStart(),
(...skipping 23 matching lines...) Expand all
599 if (pending_write_ != NULL) return 0; 618 if (pending_write_ != NULL) return 0;
600 if (num_bytes > kBufferSize) num_bytes = kBufferSize; 619 if (num_bytes > kBufferSize) num_bytes = kBufferSize;
601 if (SupportsOverlappedIO()) { 620 if (SupportsOverlappedIO()) {
602 if (completion_port_ == INVALID_HANDLE_VALUE) return 0; 621 if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
603 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); 622 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
604 pending_write_->Write(buffer, num_bytes); 623 pending_write_->Write(buffer, num_bytes);
605 if (!IssueWrite()) return -1; 624 if (!IssueWrite()) return -1;
606 return num_bytes; 625 return num_bytes;
607 } else { 626 } else {
608 // In the case of stdout and stderr, OverlappedIO is not supported. 627 // In the case of stdout and stderr, OverlappedIO is not supported.
609 // Here we'll instead spawn a new thread for each write, to make it async. 628 // Here we'll instead use a thread, to make it async.
610 // This code is actually never exposed to the user, as stdout and stderr is 629 // This code is actually never exposed to the user, as stdout and stderr is
611 // not available as a RawSocket, but only wrapped in a Socket. 630 // not available as a RawSocket, but only wrapped in a Socket.
612 // Note that we return '0', unless a thread have already completed a write. 631 // Note that we return '0', unless a thread have already completed a write.
613 // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541.
614 if (thread_wrote_ > 0) { 632 if (thread_wrote_ > 0) {
615 if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; 633 if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
616 thread_wrote_ -= num_bytes; 634 thread_wrote_ -= num_bytes;
617 return num_bytes; 635 return num_bytes;
618 } 636 }
619 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); 637 // Double-checked locking, to avoid taking the lock in most cases.
Søren Gjesse 2013/10/02 08:49:22 You need to hold the lock before accessing shared
Anders Johnsen 2013/10/02 10:16:59 Done.
620 pending_write_->Write(buffer, num_bytes); 638 if (!write_thread_exists) {
621 // Completing asynchronously through thread. 639 MonitorLocker locker(write_monitor);
622 uint32_t tid; 640 if (!write_thread_exists) {
623 uintptr_t thread_handle = 641 write_thread_exists = true;
624 _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid); 642 uint32_t tid;
625 if (thread_handle == -1) { 643 uintptr_t thread_handle =
626 FATAL("Failed to start write file thread"); 644 _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid);
645 // Completing asynchronously through thread.
646 if (thread_handle == -1) {
647 FATAL("Failed to start write file thread");
648 }
649 while (!write_thread_running) {
650 // Wait until we the thread is running.
651 locker.Wait(Monitor::kNoTimeout);
652 }
653 }
654 }
655 // Double-checked locking, to avoid taking the lock in most cases.
656 if (write_handle == NULL) {
657 MonitorLocker locker(write_monitor);
658 if (write_handle == NULL) {
659 // Create buffer and notify thread about the new handle.
660 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
661 pending_write_->Write(buffer, num_bytes);
662 write_handle = this;
663 locker.Notify();
664 }
627 } 665 }
628 return 0; 666 return 0;
629 } 667 }
630 } 668 }
631 669
632 670
633 bool ClientSocket::LoadDisconnectEx() { 671 bool ClientSocket::LoadDisconnectEx() {
634 // Load the DisconnectEx function into memory using WSAIoctl. 672 // Load the DisconnectEx function into memory using WSAIoctl.
635 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; 673 GUID guid_disconnect_ex = WSAID_DISCONNECTEX;
636 DWORD bytes; 674 DWORD bytes;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 intptr_t result; 1029 intptr_t result;
992 completion_port_ = 1030 completion_port_ =
993 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); 1031 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
994 if (completion_port_ == NULL) { 1032 if (completion_port_ == NULL) {
995 FATAL("Completion port creation failed"); 1033 FATAL("Completion port creation failed");
996 } 1034 }
997 shutdown_ = false; 1035 shutdown_ = false;
998 } 1036 }
999 1037
1000 1038
1001 EventHandlerImplementation::~EventHandlerImplementation() { 1039 EventHandlerImplementation::~EventHandlerImplementation() {
Søren Gjesse 2013/10/02 08:49:22 Take the lock before looking at shared data.
Anders Johnsen 2013/10/02 10:16:59 Done.
1040 if (write_thread_exists) {
1041 ASSERT(write_handle == NULL);
1042 MonitorLocker locker(write_monitor);
1043 write_thread_running = false;
1044 locker.Notify();
1045 while (write_thread_exists) {
1046 locker.Wait(Monitor::kNoTimeout);
1047 }
1048 }
1002 CloseHandle(completion_port_); 1049 CloseHandle(completion_port_);
1003 } 1050 }
1004 1051
1005 1052
1006 int64_t EventHandlerImplementation::GetTimeout() { 1053 int64_t EventHandlerImplementation::GetTimeout() {
1007 if (!timeout_queue_.HasTimeout()) { 1054 if (!timeout_queue_.HasTimeout()) {
1008 return kInfinityTimeout; 1055 return kInfinityTimeout;
1009 } 1056 }
1010 int64_t millis = timeout_queue_.CurrentTimeout() - 1057 int64_t millis = timeout_queue_.CurrentTimeout() -
1011 TimerUtils::GetCurrentTimeMilliseconds(); 1058 TimerUtils::GetCurrentTimeMilliseconds();
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 1146
1100 1147
1101 void EventHandlerImplementation::Shutdown() { 1148 void EventHandlerImplementation::Shutdown() {
1102 SendData(kShutdownId, 0, 0); 1149 SendData(kShutdownId, 0, 0);
1103 } 1150 }
1104 1151
1105 } // namespace bin 1152 } // namespace bin
1106 } // namespace dart 1153 } // namespace dart
1107 1154
1108 #endif // defined(TARGET_OS_WINDOWS) 1155 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698