37 #ifndef LELY_IO_IOCP_COUNT
38 #define LELY_IO_IOCP_COUNT \
39 MAX((LELY_VLA_SIZE_MAX / sizeof(OVERLAPPED_ENTRY)), 1)
50 static void CALLBACK io_poll_kill_func(ULONG_PTR Parameter);
54 static const struct io_svc_vtbl io_poll_svc_vtbl = {
60 static void *io_poll_poll_self(
const ev_poll_t *poll);
61 static int io_poll_poll_wait(
ev_poll_t *poll,
int timeout);
62 static int io_poll_poll_kill(
ev_poll_t *poll,
void *thr);
76 HANDLE CompletionPort;
92 io_poll_free(
void *ptr)
103 DWORD dwErrCode = GetLastError();
108 poll->poll_vptr = &io_poll_poll_vtbl;
110 poll->CompletionPort = CreateIoCompletionPort(
111 INVALID_HANDLE_VALUE, NULL, 0, 0);
112 if (!poll->CompletionPort) {
113 dwErrCode = GetLastError();
114 goto error_CreateIoCompletionPort;
122 error_CreateIoCompletionPort:
123 SetLastError(dwErrCode);
134 CloseHandle(poll->CompletionPort);
144 dwErrCode = GetLastError();
148 io_poll_t *tmp = io_poll_init(poll, ctx);
150 dwErrCode = GetLastError();
160 SetLastError(dwErrCode);
186 return &poll->poll_vptr;
195 return CreateIoCompletionPort(handle, poll->CompletionPort, 0, 0)
207 return PostQueuedCompletionStatus(poll->CompletionPort, nbytes, 0,
214 io_poll_kill_func(ULONG_PTR Parameter)
216 *(BOOL *)(PVOID)Parameter = TRUE;
229 if (!thr.lpdwThreadId) {
231 dwThreadId = GetCurrentThreadId();
232 thr.lpdwThreadId = &dwThreadId;
239 io_poll_poll_wait(
ev_poll_t *poll_,
int timeout)
241 io_poll_t *poll = io_poll_from_poll(poll_);
242 void *thr_ = io_poll_poll_self(poll_);
245 DWORD dwMilliseconds = timeout < 0 ? INFINITE : (DWORD)timeout;
248 DWORD dwErrCode = GetLastError();
250 OVERLAPPED_ENTRY CompletionPortEntries[LELY_IO_IOCP_COUNT];
251 ULONG ulNumEntriesRemoved = 0;
256 BOOL fSuccess = GetQueuedCompletionStatusEx(
257 poll->CompletionPort, CompletionPortEntries,
258 LELY_IO_IOCP_COUNT, &ulNumEntriesRemoved,
259 dwMilliseconds, TRUE);
265 if (GetLastError() == WAIT_TIMEOUT) {
266 if (dwMilliseconds && timeout < 0)
269 dwErrCode = GetLastError();
275 for (ULONG i = 0; i < ulNumEntriesRemoved; i++) {
276 LPOVERLAPPED_ENTRY lpEntry = &CompletionPortEntries[i];
277 LPOVERLAPPED lpOverlapped = lpEntry->lpOverlapped;
283 assert(lpfnRtlNtStatusToDosError);
284 DWORD dwErrorCode = lpfnRtlNtStatusToDosError(
285 lpOverlapped->Internal);
286 cp->
func(cp, lpEntry->dwNumberOfBytesTransferred,
293 }
while (ulNumEntriesRemoved == LELY_IO_IOCP_COUNT);
294 thr->stopped = FALSE;
296 SetLastError(dwErrCode);
301 io_poll_poll_kill(
ev_poll_t *poll,
void *thr_)
310 HANDLE hThread = OpenThread(
311 THREAD_SET_CONTEXT, FALSE, *thr->lpdwThreadId);
315 if (!QueueUserAPC(&io_poll_kill_func, hThread,
316 (ULONG_PTR)(PVOID)&thr->stopped)) {
317 DWORD dwErrCode = GetLastError();
318 CloseHandle(hThread);
319 SetLastError(dwErrCode);
322 CloseHandle(hThread);
328 io_poll_from_svc(
const struct io_svc *svc)