36
36
37
37
typedef struct win_context_rec
38
38
{
39
- HANDLE event ;
40
- HANDLE thread ; /* waiting thread */
39
+ WSAEVENT event ;
40
+ HANDLE thread ; /* waiting thread */
41
41
} win_context_t ;
42
42
43
43
@@ -60,7 +60,7 @@ SgObject Sg_MakeSocketSelector()
60
60
61
61
SG_SET_CLASS (selector , SG_CLASS_SOCKET_SELECTOR );
62
62
63
- ctx -> event = CreateEvent ( NULL , TRUE, FALSE, NULL );
63
+ ctx -> event = WSACreateEvent ( );
64
64
if (ctx -> event == NULL ) goto err ;
65
65
66
66
ctx -> thread = NULL ;
@@ -78,7 +78,7 @@ SgObject Sg_MakeSocketSelector()
78
78
void Sg_CloseSocketSelector (SgSocketSelector * selector )
79
79
{
80
80
win_context_t * ctx = (win_context_t * )selector -> context ;
81
- CloseHandle (ctx -> event );
81
+ WSACloseEvent (ctx -> event );
82
82
Sg_UnregisterFinalizer (selector );
83
83
}
84
84
@@ -107,67 +107,75 @@ static SgObject select_socket(SOCKET fd, SgObject sockets)
107
107
SgObject Sg_SocketSelectorWait (SgSocketSelector * selector , SgObject timeout )
108
108
{
109
109
win_context_t * ctx = (win_context_t * )selector -> context ;
110
- int n = selector_sockets (selector ), millis = INFINITE , r ;
111
- HANDLE hEvents [ 2 ] ;
110
+ int n = selector_sockets (selector ), r , err = FALSE ;
111
+ const int waiting_flags = FD_READ | FD_OOB ;
112
112
struct timespec spec , * sp ;
113
+ DWORD millis = INFINITE ;
113
114
SgObject ret = SG_NIL ;
115
+ SOCKET sArray [WSA_MAXIMUM_WAIT_EVENTS ];
116
+ WSAEVENT eArray [WSA_MAXIMUM_WAIT_EVENTS ] = { NULL , };
114
117
115
118
if (ctx -> thread != NULL ) {
116
119
Sg_Error (UC ("There's a thread already waiting for %A" ), selector );
117
120
}
118
121
if (n == 0 ) return ret ;
122
+ if (n - 1 > WSA_MAXIMUM_WAIT_EVENTS ) {
123
+ Sg_Error (UC ("[Windows] More than max selectable sockets are set %d > %d" ),
124
+ n , WSA_MAXIMUM_WAIT_EVENTS );
125
+ }
119
126
ctx -> thread = GetCurrentThread ();
120
-
121
- hEvents [0 ] = CreateEvent (NULL , FALSE, FALSE, NULL );
122
- hEvents [1 ] = ctx -> event ;
123
-
124
- #define SET_EVENT (sockets , event , flags ) \
125
- do { \
126
- SgObject cp; \
127
- SG_FOR_EACH(cp, sockets) { \
128
- SG_SET_SOCKET_EVENT(SG_CAAR(cp), event, flags); \
129
- } \
127
+ eArray [n ] = ctx -> event ;
128
+ #define SET_EVENT (sockets , flags ) \
129
+ do { \
130
+ SgObject cp; \
131
+ int i = 0; \
132
+ SG_FOR_EACH(cp, sockets) { \
133
+ SgObject s = SG_CAAR(cp); \
134
+ sArray[i] = SG_SOCKET(s)->socket; \
135
+ eArray[i] = WSACreateEvent(); \
136
+ if (WSAEventSelect(sArray[i], eArray[i], flags) != 0) { \
137
+ err = TRUE; \
138
+ goto cleanup; \
139
+ } \
140
+ i++; \
141
+ } \
130
142
} while(0)
131
-
132
- SET_EVENT (selector -> sockets , hEvents [0 ], FD_READ | FD_OOB );
143
+ SET_EVENT (selector -> sockets , waiting_flags );
133
144
134
145
sp = selector_timespec (timeout , & spec );
135
146
if (sp ) {
136
147
millis = sp -> tv_sec * 1000 ;
137
148
millis += sp -> tv_nsec / 1000000 ;
138
149
}
139
150
140
- r = WaitForMultipleObjects (2 , hEvents , FALSE, millis );
141
- if (r == WAIT_OBJECT_0 + 1 ) {
142
- ResetEvent (ctx -> event );
143
- }
144
-
145
- /* Using WSAPoll to detect which sockets are ready to read */
146
- WSAPOLLFD * fds = SG_NEW_ATOMIC2 (WSAPOLLFD * , n * sizeof (WSAPOLLFD ));
147
- int i = 0 ;
148
- SgObject cp ;
149
- SG_FOR_EACH (cp , selector -> sockets ) {
150
- SgSocket * sock = SG_SOCKET (SG_CAAR (cp ));
151
- fds [i ].fd = sock -> socket ;
152
- fds [i ].events = POLLRDNORM ;
153
- i ++ ;
154
- }
155
- r = WSAPoll (fds , n , 0 ); /* We may return SG_NIL in case of interrupt */
156
- if (r == SOCKET_ERROR ) system_error (WSAGetLastError ());
157
- for (i = 0 ; i < n ; i ++ ) {
158
- if (fds [i ].revents & POLLRDNORM ) {
159
- /* collect sockets, should we use hashtable? */
160
- SgObject o = select_socket (fds [i ].fd , selector -> sockets );
161
- if (!SG_FALSEP (o )) ret = Sg_Cons (o , ret );
151
+ r = WSAWaitForMultipleEvents (n + 1 , eArray , FALSE, millis , FALSE);
152
+ for (int i = r - WSA_WAIT_EVENT_0 ; i < n ; i ++ ) {
153
+ r = WSAWaitForMultipleEvents (1 , & eArray [i ], TRUE, 0 , FALSE);
154
+ if (r != WSA_WAIT_FAILED && r != WSA_WAIT_TIMEOUT ) {
155
+ WSANETWORKEVENTS networkEvents ;
156
+ if (WSAEnumNetworkEvents (sArray [i ], eArray [i ], & networkEvents ) == 0 ) {
157
+ if ((networkEvents .lNetworkEvents & waiting_flags ) != 0 ) {
158
+ SgObject o = select_socket (sArray [i ], selector -> sockets );
159
+ if (!SG_FALSEP (o )) ret = Sg_Cons (o , ret );
160
+ }
161
+ }
162
162
}
163
163
}
164
164
165
- SET_EVENT (selector -> sockets , hEvents [0 ], 0 );
166
165
#undef SET_EVENT
167
166
168
167
strip_sockets (selector , ret );
169
- CloseHandle (hEvents [0 ]);
168
+
169
+ cleanup :
170
+ for (int i = 0 ; i < n ; i ++ ) {
171
+ if (eArray [i ]) WSACloseEvent (eArray [i ]);
172
+ }
170
173
ctx -> thread = NULL ;
174
+ if (err ) {
175
+ int e = WSAGetLastError ();
176
+ Sg_Error (UC ("Failed to wait selector: [%d] %S" ), e ,
177
+ Sg_GetLastErrorMessageWithErrorCode (e ));
178
+ }
171
179
return ret ;
172
180
}
173
181
@@ -181,6 +189,6 @@ int Sg_SocketSelectorWaitingP(SgSocketSelector *selector)
181
189
SgObject Sg_SocketSelectorInterrupt (SgSocketSelector * selector )
182
190
{
183
191
win_context_t * ctx = (win_context_t * )selector -> context ;
184
- SetEvent (ctx -> event );
192
+ WSASetEvent (ctx -> event );
185
193
return selector ;
186
194
}
0 commit comments