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

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

Issue 264613002: Use ConnectEx on Windows, to do async connect of sockets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 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
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 <winsock2.h> // NOLINT 10 #include <winsock2.h> // NOLINT
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 OverlappedBuffer* OverlappedBuffer::AllocateSendToBuffer(int buffer_size) { 66 OverlappedBuffer* OverlappedBuffer::AllocateSendToBuffer(int buffer_size) {
67 return AllocateBuffer(buffer_size, kSendTo); 67 return AllocateBuffer(buffer_size, kSendTo);
68 } 68 }
69 69
70 70
71 OverlappedBuffer* OverlappedBuffer::AllocateDisconnectBuffer() { 71 OverlappedBuffer* OverlappedBuffer::AllocateDisconnectBuffer() {
72 return AllocateBuffer(0, kDisconnect); 72 return AllocateBuffer(0, kDisconnect);
73 } 73 }
74 74
75 75
76 OverlappedBuffer* OverlappedBuffer::AllocateConnectBuffer() {
77 return AllocateBuffer(0, kConnect);
78 }
79
80
76 void OverlappedBuffer::DisposeBuffer(OverlappedBuffer* buffer) { 81 void OverlappedBuffer::DisposeBuffer(OverlappedBuffer* buffer) {
77 delete buffer; 82 delete buffer;
78 } 83 }
79 84
80 85
81 OverlappedBuffer* OverlappedBuffer::GetFromOverlapped(OVERLAPPED* overlapped) { 86 OverlappedBuffer* OverlappedBuffer::GetFromOverlapped(OVERLAPPED* overlapped) {
82 OverlappedBuffer* buffer = 87 OverlappedBuffer* buffer =
83 CONTAINING_RECORD(overlapped, OverlappedBuffer, overlapped_); 88 CONTAINING_RECORD(overlapped, OverlappedBuffer, overlapped_);
84 return buffer; 89 return buffer;
85 } 90 }
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 if (!IsClosing()) { 472 if (!IsClosing()) {
468 // Update the accepted socket to support the full range of API calls. 473 // Update the accepted socket to support the full range of API calls.
469 SOCKET s = socket(); 474 SOCKET s = socket();
470 int rc = setsockopt(buffer->client(), 475 int rc = setsockopt(buffer->client(),
471 SOL_SOCKET, 476 SOL_SOCKET,
472 SO_UPDATE_ACCEPT_CONTEXT, 477 SO_UPDATE_ACCEPT_CONTEXT,
473 reinterpret_cast<char*>(&s), sizeof(s)); 478 reinterpret_cast<char*>(&s), sizeof(s));
474 if (rc == NO_ERROR) { 479 if (rc == NO_ERROR) {
475 // Insert the accepted socket into the list. 480 // Insert the accepted socket into the list.
476 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0); 481 ClientSocket* client_socket = new ClientSocket(buffer->client(), 0);
482 client_socket->mark_connected();
477 client_socket->CreateCompletionPort(completion_port); 483 client_socket->CreateCompletionPort(completion_port);
478 if (accepted_head_ == NULL) { 484 if (accepted_head_ == NULL) {
479 accepted_head_ = client_socket; 485 accepted_head_ = client_socket;
480 accepted_tail_ = client_socket; 486 accepted_tail_ = client_socket;
481 } else { 487 } else {
482 ASSERT(accepted_tail_ != NULL); 488 ASSERT(accepted_tail_ != NULL);
483 accepted_tail_->set_next(client_socket); 489 accepted_tail_->set_next(client_socket);
484 accepted_tail_ = client_socket; 490 accepted_tail_ = client_socket;
485 } 491 }
486 } else { 492 } else {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 return true; 810 return true;
805 } 811 }
806 OverlappedBuffer::DisposeBuffer(pending_write_); 812 OverlappedBuffer::DisposeBuffer(pending_write_);
807 pending_write_ = NULL; 813 pending_write_ = NULL;
808 HandleIssueError(); 814 HandleIssueError();
809 return false; 815 return false;
810 } 816 }
811 817
812 818
813 void ClientSocket::IssueDisconnect() { 819 void ClientSocket::IssueDisconnect() {
814 Dart_Port p = port();
815 OverlappedBuffer* buffer = OverlappedBuffer::AllocateDisconnectBuffer(); 820 OverlappedBuffer* buffer = OverlappedBuffer::AllocateDisconnectBuffer();
816 BOOL ok = DisconnectEx_( 821 BOOL ok = DisconnectEx_(
817 socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0); 822 socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
818 if (!ok && WSAGetLastError() != WSA_IO_PENDING) { 823 if (ok || WSAGetLastError() != WSA_IO_PENDING) {
Søren Gjesse 2014/05/01 07:19:26 When is it possible to get a success here? Please
Anders Johnsen 2014/05/01 08:05:11 "On success, the DisconnectEx function returns TRU
819 DisconnectComplete(buffer); 824 DisconnectComplete(buffer);
820 } 825 }
826 Dart_Port p = port();
821 if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent); 827 if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent);
828 port_ = ILLEGAL_PORT;
822 } 829 }
823 830
824 831
825 void ClientSocket::DisconnectComplete(OverlappedBuffer* buffer) { 832 void ClientSocket::DisconnectComplete(OverlappedBuffer* buffer) {
826 OverlappedBuffer::DisposeBuffer(buffer); 833 OverlappedBuffer::DisposeBuffer(buffer);
827 closesocket(socket()); 834 closesocket(socket());
828 if (data_ready_ != NULL) { 835 if (data_ready_ != NULL) {
829 OverlappedBuffer::DisposeBuffer(data_ready_); 836 OverlappedBuffer::DisposeBuffer(data_ready_);
830 } 837 }
831 // When disconnect is complete get rid of the object. 838 closed_ = true;
832 delete this;
833 } 839 }
834 840
835 841
842 void ClientSocket::ConnectComplete(OverlappedBuffer* buffer) {
843 OverlappedBuffer::DisposeBuffer(buffer);
Søren Gjesse 2014/05/01 07:19:26 Please add a comment on this call, e.g. " // Updat
Anders Johnsen 2014/05/01 08:05:11 Done.
844 setsockopt(socket(), SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
845 connected_ = true;
846 Dart_Port p = port();
847 if (p != ILLEGAL_PORT) {
848 // If the port is set, we already listen for this socket in Dart.
849 // Handle the cases here.
850 if (!IsClosedRead()) {
851 IssueRead();
852 }
853 if (!IsClosedWrite()) {
854 DartUtils::PostInt32(p, 1 << kOutEvent);
855 }
856 }
857 }
858
859
836 void ClientSocket::EnsureInitialized( 860 void ClientSocket::EnsureInitialized(
837 EventHandlerImplementation* event_handler) { 861 EventHandlerImplementation* event_handler) {
838 ScopedLock lock(this); 862 ScopedLock lock(this);
839 if (completion_port_ == INVALID_HANDLE_VALUE) { 863 if (completion_port_ == INVALID_HANDLE_VALUE) {
840 ASSERT(event_handler_ == NULL); 864 ASSERT(event_handler_ == NULL);
841 event_handler_ = event_handler; 865 event_handler_ = event_handler;
842 CreateCompletionPort(event_handler_->completion_port()); 866 CreateCompletionPort(event_handler_->completion_port());
843 } 867 }
844 } 868 }
845 869
846 870
847 bool ClientSocket::IsClosed() { 871 bool ClientSocket::IsClosed() {
848 return false; 872 return closed_;
849 } 873 }
850 874
851 875
852 bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) { 876 bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) {
853 ScopedLock lock(this); 877 ScopedLock lock(this);
854 ASSERT(completion_port_ != INVALID_HANDLE_VALUE); 878 ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
855 ASSERT(pending_write_ != NULL); 879 ASSERT(pending_write_ != NULL);
856 ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo); 880 ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo);
857 881
858 int rc = WSASendTo(socket(), 882 int rc = WSASendTo(socket(),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 closesocket(socket()); 949 closesocket(socket());
926 MarkClosedRead(); 950 MarkClosedRead();
927 MarkClosedWrite(); 951 MarkClosedWrite();
928 } 952 }
929 953
930 954
931 static void DeleteIfClosed(Handle* handle) { 955 static void DeleteIfClosed(Handle* handle) {
932 if (handle->IsClosed()) { 956 if (handle->IsClosed()) {
933 Dart_Port port = handle->port(); 957 Dart_Port port = handle->port();
934 delete handle; 958 delete handle;
935 DartUtils::PostInt32(port, 1 << kDestroyedEvent); 959 if (port != ILLEGAL_PORT) {
960 DartUtils::PostInt32(port, 1 << kDestroyedEvent);
961 }
936 } 962 }
937 } 963 }
938 964
939 965
940 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) { 966 void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) {
941 if (msg->id == kTimeoutId) { 967 if (msg->id == kTimeoutId) {
942 // Change of timeout request. Just set the new timeout and port as the 968 // Change of timeout request. Just set the new timeout and port as the
943 // completion thread will use the new timeout value for its next wait. 969 // completion thread will use the new timeout value for its next wait.
944 timeout_queue_.UpdateTimeout(msg->dart_port, msg->data); 970 timeout_queue_.UpdateTimeout(msg->dart_port, msg->data);
945 } else if (msg->id == kShutdownId) { 971 } else if (msg->id == kShutdownId) {
(...skipping 21 matching lines...) Expand all
967 } 993 }
968 // Always keep 5 outstanding accepts going, to enhance performance. 994 // Always keep 5 outstanding accepts going, to enhance performance.
969 while (listen_socket->pending_accept_count() < 5) { 995 while (listen_socket->pending_accept_count() < 5) {
970 bool accept_success = listen_socket->IssueAccept(); 996 bool accept_success = listen_socket->IssueAccept();
971 if (!accept_success) { 997 if (!accept_success) {
972 HandleError(listen_socket); 998 HandleError(listen_socket);
973 break; 999 break;
974 } 1000 }
975 } 1001 }
976 } 1002 }
977
978 if ((msg->data & (1 << kCloseCommand)) != 0) {
979 listen_socket->Close();
980 }
981 } else { 1003 } else {
982 handle->EnsureInitialized(this); 1004 handle->EnsureInitialized(this);
983 1005
984 Handle::ScopedLock lock(handle); 1006 Handle::ScopedLock lock(handle);
985 1007
986 // Only set mask if we turned on kInEvent or kOutEvent. 1008 // Only set mask if we turned on kInEvent or kOutEvent.
987 if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) { 1009 if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) {
988 handle->SetPortAndMask(msg->dart_port, msg->data); 1010 handle->SetPortAndMask(msg->dart_port, msg->data);
989 } 1011 }
990 1012
991 // Issue a read. 1013 // Issue a read.
992 if ((msg->data & (1 << kInEvent)) != 0) { 1014 if ((msg->data & (1 << kInEvent)) != 0) {
993 handle->SetPortAndMask(msg->dart_port, msg->data);
994 if (handle->is_datagram_socket()) { 1015 if (handle->is_datagram_socket()) {
995 handle->IssueRecvFrom(); 1016 handle->IssueRecvFrom();
1017 } else if (handle->is_client_socket()) {
1018 if (reinterpret_cast<ClientSocket*>(handle)->is_connected()) {
1019 handle->IssueRead();
1020 }
996 } else { 1021 } else {
997 handle->IssueRead(); 1022 handle->IssueRead();
998 } 1023 }
999 } 1024 }
1000 1025
1001 // If out events (can write events) have been requested, and there 1026 // If out events (can write events) have been requested, and there
1002 // are no pending writes, meaning any writes are already complete, 1027 // are no pending writes, meaning any writes are already complete,
1003 // post an out event immediately. 1028 // post an out event immediately.
1004 if ((msg->data & (1 << kOutEvent)) != 0) { 1029 if ((msg->data & (1 << kOutEvent)) != 0) {
1005 handle->SetPortAndMask(msg->dart_port, msg->data);
1006 if (!handle->HasPendingWrite()) { 1030 if (!handle->HasPendingWrite()) {
1007 int event_mask = (1 << kOutEvent); 1031 if (handle->is_client_socket()) {
1008 DartUtils::PostInt32(handle->port(), event_mask); 1032 if (reinterpret_cast<ClientSocket*>(handle)->is_connected()) {
1033 DartUtils::PostInt32(handle->port(), 1 << kOutEvent);
1034 }
1035 } else {
1036 DartUtils::PostInt32(handle->port(), 1 << kOutEvent);
1037 }
1009 } 1038 }
1010 } 1039 }
1011 1040
1012 if (handle->is_client_socket()) { 1041 if (handle->is_client_socket()) {
1013 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle); 1042 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle);
1014 if ((msg->data & (1 << kShutdownReadCommand)) != 0) { 1043 if ((msg->data & (1 << kShutdownReadCommand)) != 0) {
1015 client_socket->Shutdown(SD_RECEIVE); 1044 client_socket->Shutdown(SD_RECEIVE);
1016 } 1045 }
1017 1046
1018 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) { 1047 if ((msg->data & (1 << kShutdownWriteCommand)) != 0) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 1136
1108 1137
1109 void EventHandlerImplementation::HandleWrite(Handle* handle, 1138 void EventHandlerImplementation::HandleWrite(Handle* handle,
1110 int bytes, 1139 int bytes,
1111 OverlappedBuffer* buffer) { 1140 OverlappedBuffer* buffer) {
1112 handle->WriteComplete(buffer); 1141 handle->WriteComplete(buffer);
1113 1142
1114 if (bytes >= 0) { 1143 if (bytes >= 0) {
1115 if (!handle->IsError() && !handle->IsClosing()) { 1144 if (!handle->IsError() && !handle->IsClosing()) {
1116 int event_mask = 1 << kOutEvent; 1145 int event_mask = 1 << kOutEvent;
1146 ASSERT(!handle->is_client_socket() ||
1147 reinterpret_cast<ClientSocket*>(handle)->is_connected());
1117 if ((handle->mask() & event_mask) != 0) { 1148 if ((handle->mask() & event_mask) != 0) {
1118 DartUtils::PostInt32(handle->port(), event_mask); 1149 DartUtils::PostInt32(handle->port(), event_mask);
1119 } 1150 }
1120 } 1151 }
1121 } else { 1152 } else {
1122 HandleError(handle); 1153 HandleError(handle);
1123 } 1154 }
1124 1155
1125 DeleteIfClosed(handle); 1156 DeleteIfClosed(handle);
1126 } 1157 }
1127 1158
1128 1159
1129 void EventHandlerImplementation::HandleDisconnect( 1160 void EventHandlerImplementation::HandleDisconnect(
1130 ClientSocket* client_socket, 1161 ClientSocket* client_socket,
1131 int bytes, 1162 int bytes,
1132 OverlappedBuffer* buffer) { 1163 OverlappedBuffer* buffer) {
1133 client_socket->DisconnectComplete(buffer); 1164 client_socket->DisconnectComplete(buffer);
1165 DeleteIfClosed(client_socket);
1134 } 1166 }
1135 1167
1168
1169 void EventHandlerImplementation::HandleConnect(
1170 ClientSocket* client_socket,
1171 int bytes,
1172 OverlappedBuffer* buffer) {
1173 if (bytes < 0) {
1174 HandleError(client_socket);
1175 OverlappedBuffer::DisposeBuffer(buffer);
1176 } else {
1177 client_socket->ConnectComplete(buffer);
1178 }
1179 }
1180
1181
1136 void EventHandlerImplementation::HandleTimeout() { 1182 void EventHandlerImplementation::HandleTimeout() {
1137 if (!timeout_queue_.HasTimeout()) return; 1183 if (!timeout_queue_.HasTimeout()) return;
1138 DartUtils::PostNull(timeout_queue_.CurrentPort()); 1184 DartUtils::PostNull(timeout_queue_.CurrentPort());
1139 timeout_queue_.RemoveCurrent(); 1185 timeout_queue_.RemoveCurrent();
1140 } 1186 }
1141 1187
1142 1188
1143 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes, 1189 void EventHandlerImplementation::HandleIOCompletion(DWORD bytes,
1144 ULONG_PTR key, 1190 ULONG_PTR key,
1145 OVERLAPPED* overlapped) { 1191 OVERLAPPED* overlapped) {
(...skipping 18 matching lines...) Expand all
1164 case OverlappedBuffer::kSendTo: { 1210 case OverlappedBuffer::kSendTo: {
1165 Handle* handle = reinterpret_cast<Handle*>(key); 1211 Handle* handle = reinterpret_cast<Handle*>(key);
1166 HandleWrite(handle, bytes, buffer); 1212 HandleWrite(handle, bytes, buffer);
1167 break; 1213 break;
1168 } 1214 }
1169 case OverlappedBuffer::kDisconnect: { 1215 case OverlappedBuffer::kDisconnect: {
1170 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key); 1216 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key);
1171 HandleDisconnect(client_socket, bytes, buffer); 1217 HandleDisconnect(client_socket, bytes, buffer);
1172 break; 1218 break;
1173 } 1219 }
1220 case OverlappedBuffer::kConnect: {
1221 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key);
1222 HandleConnect(client_socket, bytes, buffer);
1223 break;
1224 }
1174 default: 1225 default:
1175 UNREACHABLE(); 1226 UNREACHABLE();
1176 } 1227 }
1177 } 1228 }
1178 1229
1179 1230
1180 EventHandlerImplementation::EventHandlerImplementation() { 1231 EventHandlerImplementation::EventHandlerImplementation() {
1181 intptr_t result; 1232 intptr_t result;
1182 completion_port_ = 1233 completion_port_ =
1183 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); 1234 CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 1340
1290 1341
1291 void EventHandlerImplementation::Shutdown() { 1342 void EventHandlerImplementation::Shutdown() {
1292 SendData(kShutdownId, 0, 0); 1343 SendData(kShutdownId, 0, 0);
1293 } 1344 }
1294 1345
1295 } // namespace bin 1346 } // namespace bin
1296 } // namespace dart 1347 } // namespace dart
1297 1348
1298 #endif // defined(TARGET_OS_WINDOWS) 1349 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698