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_exists_(false), |
| 127 read_thread_monitor_(new Monitor()) { |
125 InitializeCriticalSection(&cs_); | 128 InitializeCriticalSection(&cs_); |
126 } | 129 } |
127 | 130 |
128 | 131 |
129 Handle::~Handle() { | 132 Handle::~Handle() { |
| 133 delete read_thread_monitor_; |
130 DeleteCriticalSection(&cs_); | 134 DeleteCriticalSection(&cs_); |
131 } | 135 } |
132 | 136 |
133 | 137 |
134 void Handle::Lock() { | 138 void Handle::Lock() { |
135 EnterCriticalSection(&cs_); | 139 EnterCriticalSection(&cs_); |
136 } | 140 } |
137 | 141 |
138 | 142 |
139 void Handle::Unlock() { | 143 void Handle::Unlock() { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 ScopedLock lock(this); | 194 ScopedLock lock(this); |
191 // Currently only one outstanding read at the time. | 195 // Currently only one outstanding read at the time. |
192 ASSERT(pending_read_ == buffer); | 196 ASSERT(pending_read_ == buffer); |
193 ASSERT(data_ready_ == NULL); | 197 ASSERT(data_ready_ == NULL); |
194 if (!IsClosing() && !buffer->IsEmpty()) { | 198 if (!IsClosing() && !buffer->IsEmpty()) { |
195 data_ready_ = pending_read_; | 199 data_ready_ = pending_read_; |
196 } else { | 200 } else { |
197 OverlappedBuffer::DisposeBuffer(buffer); | 201 OverlappedBuffer::DisposeBuffer(buffer); |
198 } | 202 } |
199 pending_read_ = NULL; | 203 pending_read_ = NULL; |
| 204 |
| 205 // Join the Reader thread if there is one. |
| 206 ThreadId to_join; |
| 207 { |
| 208 MonitorLocker ml(read_thread_monitor_); |
| 209 while (read_thread_exists_) { |
| 210 ml.Wait(); |
| 211 } |
| 212 to_join = read_thread_id_; |
| 213 read_thread_id = Thread::kInvalidThreadId; |
| 214 } |
| 215 if (to_join != Thread::kInvalidThreadId) { |
| 216 Thread::Join(to_join); |
| 217 } |
200 } | 218 } |
201 | 219 |
202 | 220 |
203 void Handle::RecvFromComplete(OverlappedBuffer* buffer) { | 221 void Handle::RecvFromComplete(OverlappedBuffer* buffer) { |
204 ReadComplete(buffer); | 222 ReadComplete(buffer); |
205 } | 223 } |
206 | 224 |
207 | 225 |
208 void Handle::WriteComplete(OverlappedBuffer* buffer) { | 226 void Handle::WriteComplete(OverlappedBuffer* buffer) { |
209 ScopedLock lock(this); | 227 ScopedLock lock(this); |
210 // Currently only one outstanding write at the time. | 228 // Currently only one outstanding write at the time. |
211 ASSERT(pending_write_ == buffer); | 229 ASSERT(pending_write_ == buffer); |
212 OverlappedBuffer::DisposeBuffer(buffer); | 230 OverlappedBuffer::DisposeBuffer(buffer); |
213 pending_write_ = NULL; | 231 pending_write_ = NULL; |
214 } | 232 } |
215 | 233 |
216 | 234 |
217 static void ReadFileThread(uword args) { | 235 static void ReadFileThread(uword args) { |
218 Handle* handle = reinterpret_cast<Handle*>(args); | 236 Handle* handle = reinterpret_cast<Handle*>(args); |
219 handle->ReadSyncCompleteAsync(); | 237 handle->ReadSyncCompleteAsync(); |
220 } | 238 } |
221 | 239 |
222 | 240 |
223 void Handle::ReadSyncCompleteAsync() { | 241 void Handle::ReadSyncCompleteAsync() { |
224 ASSERT(pending_read_ != NULL); | 242 ASSERT(pending_read_ != NULL); |
225 ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize); | 243 ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize); |
| 244 { |
| 245 MonitorLocker ml(read_thread_monitor_); |
| 246 read_thread_id_ = Thread::GetCurrentThreadId(); |
| 247 read_thread_exists_ = true; |
| 248 ml.Notify(); |
| 249 } |
226 | 250 |
227 DWORD buffer_size = pending_read_->GetBufferSize(); | 251 DWORD buffer_size = pending_read_->GetBufferSize(); |
228 if (GetFileType(handle_) == FILE_TYPE_CHAR) { | 252 if (GetFileType(handle_) == FILE_TYPE_CHAR) { |
229 buffer_size = kStdOverlappedBufferSize; | 253 buffer_size = kStdOverlappedBufferSize; |
230 } | 254 } |
231 DWORD bytes_read = 0; | 255 DWORD bytes_read = 0; |
232 BOOL ok = ReadFile(handle_, | 256 BOOL ok = ReadFile(handle_, |
233 pending_read_->GetBufferStart(), | 257 pending_read_->GetBufferStart(), |
234 buffer_size, | 258 buffer_size, |
235 &bytes_read, | 259 &bytes_read, |
236 NULL); | 260 NULL); |
237 if (!ok) { | 261 if (!ok) { |
238 bytes_read = 0; | 262 bytes_read = 0; |
239 } | 263 } |
240 OVERLAPPED* overlapped = pending_read_->GetCleanOverlapped(); | 264 OVERLAPPED* overlapped = pending_read_->GetCleanOverlapped(); |
241 ok = PostQueuedCompletionStatus(event_handler_->completion_port(), | 265 ok = PostQueuedCompletionStatus(event_handler_->completion_port(), |
242 bytes_read, | 266 bytes_read, |
243 reinterpret_cast<ULONG_PTR>(this), | 267 reinterpret_cast<ULONG_PTR>(this), |
244 overlapped); | 268 overlapped); |
245 if (!ok) { | 269 if (!ok) { |
246 FATAL("PostQueuedCompletionStatus failed"); | 270 FATAL("PostQueuedCompletionStatus failed"); |
247 } | 271 } |
| 272 { |
| 273 MonitorLocker ml(read_thread_monitor_); |
| 274 read_thread_exists_ = false; |
| 275 ml.Notify(); |
| 276 } |
248 } | 277 } |
249 | 278 |
250 | 279 |
251 bool Handle::IssueRead() { | 280 bool Handle::IssueRead() { |
252 ScopedLock lock(this); | 281 ScopedLock lock(this); |
253 ASSERT(type_ != kListenSocket); | 282 ASSERT(type_ != kListenSocket); |
254 ASSERT(pending_read_ == NULL); | 283 ASSERT(pending_read_ == NULL); |
255 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); | 284 OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize); |
256 if (SupportsOverlappedIO()) { | 285 if (SupportsOverlappedIO()) { |
257 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); | 286 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); |
(...skipping 12 matching lines...) Expand all Loading... |
270 HandleIssueError(); | 299 HandleIssueError(); |
271 return false; | 300 return false; |
272 } else { | 301 } else { |
273 // Completing asynchronously through thread. | 302 // Completing asynchronously through thread. |
274 pending_read_ = buffer; | 303 pending_read_ = buffer; |
275 int result = Thread::Start(ReadFileThread, | 304 int result = Thread::Start(ReadFileThread, |
276 reinterpret_cast<uword>(this)); | 305 reinterpret_cast<uword>(this)); |
277 if (result != 0) { | 306 if (result != 0) { |
278 FATAL1("Failed to start read file thread %d", result); | 307 FATAL1("Failed to start read file thread %d", result); |
279 } | 308 } |
| 309 { |
| 310 MonitorLocker ml(read_thread_monitor_); |
| 311 while (!read_thread_exists_) { |
| 312 ml.Wait(); |
| 313 } |
| 314 ASSERT(read_thread_id_ != Thread::kInvalidThreadId); |
| 315 } |
280 return true; | 316 return true; |
281 } | 317 } |
282 } | 318 } |
283 | 319 |
284 | 320 |
285 bool Handle::IssueRecvFrom() { | 321 bool Handle::IssueRecvFrom() { |
286 return false; | 322 return false; |
287 } | 323 } |
288 | 324 |
289 | 325 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 | 706 |
671 static void WriteFileThread(uword args) { | 707 static void WriteFileThread(uword args) { |
672 StdHandle* handle = reinterpret_cast<StdHandle*>(args); | 708 StdHandle* handle = reinterpret_cast<StdHandle*>(args); |
673 handle->RunWriteLoop(); | 709 handle->RunWriteLoop(); |
674 } | 710 } |
675 | 711 |
676 | 712 |
677 void StdHandle::RunWriteLoop() { | 713 void StdHandle::RunWriteLoop() { |
678 write_monitor_->Enter(); | 714 write_monitor_->Enter(); |
679 write_thread_running_ = true; | 715 write_thread_running_ = true; |
| 716 thread_id_ = Thread::GetCurrentThreadId(); |
680 // Notify we have started. | 717 // Notify we have started. |
681 write_monitor_->Notify(); | 718 write_monitor_->Notify(); |
682 | 719 |
683 while (write_thread_running_) { | 720 while (write_thread_running_) { |
684 write_monitor_->Wait(Monitor::kNoTimeout); | 721 write_monitor_->Wait(Monitor::kNoTimeout); |
685 if (pending_write_ != NULL) { | 722 if (pending_write_ != NULL) { |
686 // We woke up and had a pending write. Execute it. | 723 // We woke up and had a pending write. Execute it. |
687 WriteSyncCompleteAsync(); | 724 WriteSyncCompleteAsync(); |
688 } | 725 } |
689 } | 726 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 | 792 |
756 | 793 |
757 void StdHandle::DoClose() { | 794 void StdHandle::DoClose() { |
758 MonitorLocker locker(write_monitor_); | 795 MonitorLocker locker(write_monitor_); |
759 if (write_thread_exists_) { | 796 if (write_thread_exists_) { |
760 write_thread_running_ = false; | 797 write_thread_running_ = false; |
761 locker.Notify(); | 798 locker.Notify(); |
762 while (write_thread_exists_) { | 799 while (write_thread_exists_) { |
763 locker.Wait(Monitor::kNoTimeout); | 800 locker.Wait(Monitor::kNoTimeout); |
764 } | 801 } |
| 802 Thread::Join(thread_id_); |
765 } | 803 } |
766 Handle::DoClose(); | 804 Handle::DoClose(); |
767 } | 805 } |
768 | 806 |
769 | 807 |
770 bool ClientSocket::LoadDisconnectEx() { | 808 bool ClientSocket::LoadDisconnectEx() { |
771 // Load the DisconnectEx function into memory using WSAIoctl. | 809 // Load the DisconnectEx function into memory using WSAIoctl. |
772 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; | 810 GUID guid_disconnect_ex = WSAID_DISCONNECTEX; |
773 DWORD bytes; | 811 DWORD bytes; |
774 int status = WSAIoctl(socket(), | 812 int status = WSAIoctl(socket(), |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 HandleConnect(client_socket, bytes, buffer); | 1309 HandleConnect(client_socket, bytes, buffer); |
1272 break; | 1310 break; |
1273 } | 1311 } |
1274 default: | 1312 default: |
1275 UNREACHABLE(); | 1313 UNREACHABLE(); |
1276 } | 1314 } |
1277 } | 1315 } |
1278 | 1316 |
1279 | 1317 |
1280 EventHandlerImplementation::EventHandlerImplementation() { | 1318 EventHandlerImplementation::EventHandlerImplementation() { |
| 1319 startup_monitor_ = new Monitor(); |
| 1320 handler_thread_id_ = Thread::kInvalidThreadId; |
1281 completion_port_ = | 1321 completion_port_ = |
1282 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); | 1322 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); |
1283 if (completion_port_ == NULL) { | 1323 if (completion_port_ == NULL) { |
1284 FATAL("Completion port creation failed"); | 1324 FATAL("Completion port creation failed"); |
1285 } | 1325 } |
1286 shutdown_ = false; | 1326 shutdown_ = false; |
1287 } | 1327 } |
1288 | 1328 |
1289 | 1329 |
1290 EventHandlerImplementation::~EventHandlerImplementation() { | 1330 EventHandlerImplementation::~EventHandlerImplementation() { |
| 1331 Thread::Join(handler_thread_id_); |
| 1332 delete startup_monitor_; |
1291 CloseHandle(completion_port_); | 1333 CloseHandle(completion_port_); |
1292 } | 1334 } |
1293 | 1335 |
1294 | 1336 |
1295 int64_t EventHandlerImplementation::GetTimeout() { | 1337 int64_t EventHandlerImplementation::GetTimeout() { |
1296 if (!timeout_queue_.HasTimeout()) { | 1338 if (!timeout_queue_.HasTimeout()) { |
1297 return kInfinityTimeout; | 1339 return kInfinityTimeout; |
1298 } | 1340 } |
1299 int64_t millis = timeout_queue_.CurrentTimeout() - | 1341 int64_t millis = timeout_queue_.CurrentTimeout() - |
1300 TimerUtils::GetCurrentTimeMilliseconds(); | 1342 TimerUtils::GetCurrentTimeMilliseconds(); |
(...skipping 14 matching lines...) Expand all Loading... |
1315 FATAL("PostQueuedCompletionStatus failed"); | 1357 FATAL("PostQueuedCompletionStatus failed"); |
1316 } | 1358 } |
1317 } | 1359 } |
1318 | 1360 |
1319 | 1361 |
1320 void EventHandlerImplementation::EventHandlerEntry(uword args) { | 1362 void EventHandlerImplementation::EventHandlerEntry(uword args) { |
1321 EventHandler* handler = reinterpret_cast<EventHandler*>(args); | 1363 EventHandler* handler = reinterpret_cast<EventHandler*>(args); |
1322 EventHandlerImplementation* handler_impl = &handler->delegate_; | 1364 EventHandlerImplementation* handler_impl = &handler->delegate_; |
1323 ASSERT(handler_impl != NULL); | 1365 ASSERT(handler_impl != NULL); |
1324 | 1366 |
| 1367 { |
| 1368 MonitorLocker ml(handler_impl->startup_monitor_); |
| 1369 handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId(); |
| 1370 ml.Notify(); |
| 1371 } |
| 1372 |
1325 while (!handler_impl->shutdown_) { | 1373 while (!handler_impl->shutdown_) { |
1326 DWORD bytes; | 1374 DWORD bytes; |
1327 ULONG_PTR key; | 1375 ULONG_PTR key; |
1328 OVERLAPPED* overlapped; | 1376 OVERLAPPED* overlapped; |
1329 int64_t millis = handler_impl->GetTimeout(); | 1377 int64_t millis = handler_impl->GetTimeout(); |
1330 ASSERT(millis == kInfinityTimeout || millis >= 0); | 1378 ASSERT(millis == kInfinityTimeout || millis >= 0); |
1331 if (millis > kMaxInt32) millis = kMaxInt32; | 1379 if (millis > kMaxInt32) millis = kMaxInt32; |
1332 ASSERT(sizeof(int32_t) == sizeof(DWORD)); | 1380 ASSERT(sizeof(int32_t) == sizeof(DWORD)); |
1333 BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(), | 1381 BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(), |
1334 &bytes, | 1382 &bytes, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1375 } | 1423 } |
1376 | 1424 |
1377 | 1425 |
1378 void EventHandlerImplementation::Start(EventHandler* handler) { | 1426 void EventHandlerImplementation::Start(EventHandler* handler) { |
1379 int result = Thread::Start(EventHandlerEntry, | 1427 int result = Thread::Start(EventHandlerEntry, |
1380 reinterpret_cast<uword>(handler)); | 1428 reinterpret_cast<uword>(handler)); |
1381 if (result != 0) { | 1429 if (result != 0) { |
1382 FATAL1("Failed to start event handler thread %d", result); | 1430 FATAL1("Failed to start event handler thread %d", result); |
1383 } | 1431 } |
1384 | 1432 |
| 1433 { |
| 1434 MonitorLocker ml(startup_monitor_); |
| 1435 while (handler_thread_id_ == Thread::kInvalidThreadId) { |
| 1436 ml.Wait(); |
| 1437 } |
| 1438 } |
| 1439 |
1385 // Initialize Winsock32 | 1440 // Initialize Winsock32 |
1386 if (!Socket::Initialize()) { | 1441 if (!Socket::Initialize()) { |
1387 FATAL("Failed to initialized Windows sockets"); | 1442 FATAL("Failed to initialized Windows sockets"); |
1388 } | 1443 } |
1389 } | 1444 } |
1390 | 1445 |
1391 | 1446 |
1392 void EventHandlerImplementation::Shutdown() { | 1447 void EventHandlerImplementation::Shutdown() { |
1393 SendData(kShutdownId, 0, 0); | 1448 SendData(kShutdownId, 0, 0); |
1394 } | 1449 } |
1395 | 1450 |
1396 } // namespace bin | 1451 } // namespace bin |
1397 } // namespace dart | 1452 } // namespace dart |
1398 | 1453 |
1399 #endif // defined(TARGET_OS_WINDOWS) | 1454 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |