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

Unified 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: Make the thread a part of the StdHandle. 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/eventhandler_win.h ('k') | runtime/bin/socket_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/eventhandler_win.cc
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 59b22077d4d5a8f67257595bb9c41face06fa7a4..b6d40992df2f4b35b41cc05a3e290c3d6a0eca22 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -7,7 +7,6 @@
#include "bin/eventhandler.h"
-#include <process.h> // NOLINT
#include <winsock2.h> // NOLINT
#include <ws2tcpip.h> // NOLINT
#include <mswsock.h> // NOLINT
@@ -19,7 +18,7 @@
#include "bin/log.h"
#include "bin/socket.h"
#include "bin/utils.h"
-#include "platform/thread.h"
+#include "vm/thread.h"
namespace dart {
@@ -107,7 +106,6 @@ Handle::Handle(HANDLE handle)
pending_read_(NULL),
pending_write_(NULL),
last_error_(NOERROR),
- thread_wrote_(0),
flags_(0) {
InitializeCriticalSection(&cs_);
}
@@ -123,7 +121,6 @@ Handle::Handle(HANDLE handle, Dart_Port port)
pending_read_(NULL),
pending_write_(NULL),
last_error_(NOERROR),
- thread_wrote_(0),
flags_(0) {
InitializeCriticalSection(&cs_);
}
@@ -211,10 +208,9 @@ void Handle::WriteComplete(OverlappedBuffer* buffer) {
}
-static unsigned int __stdcall ReadFileThread(void* args) {
+static void ReadFileThread(uword args) {
Handle* handle = reinterpret_cast<Handle*>(args);
handle->ReadSyncCompleteAsync();
- return 0;
}
@@ -273,11 +269,10 @@ bool Handle::IssueRead() {
} else {
// Completing asynchronously through thread.
pending_read_ = buffer;
- uint32_t tid;
- uintptr_t thread_handle =
- _beginthreadex(NULL, 32 * 1024, ReadFileThread, this, 0, &tid);
- if (thread_handle == -1) {
- FATAL("Failed to start read file thread");
+ int result = dart::Thread::Start(ReadFileThread,
+ reinterpret_cast<uword>(this));
+ if (result != 0) {
+ FATAL("Failed to start read file thread %d", result);
}
return true;
}
@@ -333,18 +328,6 @@ bool FileHandle::IsClosed() {
}
-void FileHandle::DoClose() {
- if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) {
- int fd = _open("NUL", _O_WRONLY);
- ASSERT(fd >= 0);
- _dup2(fd, _fileno(stdout));
- close(fd);
- } else {
- Handle::DoClose();
- }
-}
-
-
void DirectoryWatchHandle::EnsureInitialized(
EventHandlerImplementation* event_handler) {
ScopedLock lock(this);
@@ -560,14 +543,46 @@ int Handle::Read(void* buffer, int num_bytes) {
}
-static unsigned int __stdcall WriteFileThread(void* args) {
- Handle* handle = reinterpret_cast<Handle*>(args);
- handle->WriteSyncCompleteAsync();
- return 0;
+int Handle::Write(const void* buffer, int num_bytes) {
+ ScopedLock lock(this);
+ if (pending_write_ != NULL) return 0;
+ if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+ ASSERT(SupportsOverlappedIO());
+ if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+ pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
+ pending_write_->Write(buffer, num_bytes);
+ if (!IssueWrite()) return -1;
+ return num_bytes;
}
-void Handle::WriteSyncCompleteAsync() {
+static void WriteFileThread(uword args) {
+ StdHandle* handle = reinterpret_cast<StdHandle*>(args);
+ handle->RunWriteLoop();
+}
+
+
+void StdHandle::RunWriteLoop() {
+ write_monitor_->Enter();
+ write_thread_running_ = true;
+ // Notify we have started.
+ write_monitor_->Notify();
+
+ while (write_thread_running_) {
+ write_monitor_->Wait(Monitor::kNoTimeout);
+ if (pending_write_ != NULL) {
+ // We woke up and had a pending write. Execute it.
+ WriteSyncCompleteAsync();
+ }
+ }
+
+ write_thread_exists_ = false;
+ write_monitor_->Notify();
+ write_monitor_->Exit();
+}
+
+
+void StdHandle::WriteSyncCompleteAsync() {
ASSERT(pending_write_ != NULL);
DWORD bytes_written = -1;
@@ -593,39 +608,57 @@ void Handle::WriteSyncCompleteAsync() {
}
}
-
-int Handle::Write(const void* buffer, int num_bytes) {
+int StdHandle::Write(const void* buffer, int num_bytes) {
ScopedLock lock(this);
if (pending_write_ != NULL) return 0;
if (num_bytes > kBufferSize) num_bytes = kBufferSize;
- if (SupportsOverlappedIO()) {
- if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
- pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
- pending_write_->Write(buffer, num_bytes);
- if (!IssueWrite()) return -1;
+ // In the case of stdout and stderr, OverlappedIO is not supported.
+ // Here we'll instead use a thread, to make it async.
+ // This code is actually never exposed to the user, as stdout and stderr is
+ // not available as a RawSocket, but only wrapped in a Socket.
+ // Note that we return '0', unless a thread have already completed a write.
+ MonitorLocker locker(write_monitor_);
+ if (thread_wrote_ > 0) {
+ if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
+ thread_wrote_ -= num_bytes;
return num_bytes;
- } else {
- // In the case of stdout and stderr, OverlappedIO is not supported.
- // Here we'll instead spawn a new thread for each write, to make it async.
- // This code is actually never exposed to the user, as stdout and stderr is
- // not available as a RawSocket, but only wrapped in a Socket.
- // Note that we return '0', unless a thread have already completed a write.
- // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541.
- if (thread_wrote_ > 0) {
- if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
- thread_wrote_ -= num_bytes;
- return num_bytes;
+ }
+ if (!write_thread_exists_) {
+ write_thread_exists_ = true;
+ int result = dart::Thread::Start(WriteFileThread,
+ reinterpret_cast<uword>(this));
+ if (result != 0) {
+ FATAL("Failed to start write file thread %d", result);
}
- pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
- pending_write_->Write(buffer, num_bytes);
- // Completing asynchronously through thread.
- uint32_t tid;
- uintptr_t thread_handle =
- _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid);
- if (thread_handle == -1) {
- FATAL("Failed to start write file thread");
+ while (!write_thread_running_) {
+ // Wait until we the thread is running.
+ locker.Wait(Monitor::kNoTimeout);
+ }
+ }
+ // Create buffer and notify thread about the new handle.
+ pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
+ pending_write_->Write(buffer, num_bytes);
+ locker.Notify();
+ return 0;
+}
+
+
+void StdHandle::DoClose() {
+ MonitorLocker locker(write_monitor_);
+ if (write_thread_exists_) {
+ write_thread_running_ = false;
+ locker.Notify();
+ while (write_thread_exists_) {
+ locker.Wait(Monitor::kNoTimeout);
}
- return 0;
+ }
+ if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) {
+ int fd = _open("NUL", _O_WRONLY);
+ ASSERT(fd >= 0);
+ _dup2(fd, _fileno(stdout));
+ close(fd);
+ } else {
+ Handle::DoClose();
}
}
« no previous file with comments | « runtime/bin/eventhandler_win.h ('k') | runtime/bin/socket_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698