26#if !LELY_NO_STDIO && _WIN32
37#ifndef LELY_IO_IOCP_COUNT
38#define LELY_IO_IOCP_COUNT \
39 MAX((LELY_VLA_SIZE_MAX / sizeof(OVERLAPPED_ENTRY)), 1)
50static void CALLBACK io_poll_kill_func(ULONG_PTR Parameter);
60static void *io_poll_poll_self(
const ev_poll_t *poll);
61static int io_poll_poll_wait(
ev_poll_t *poll,
int timeout);
62static int io_poll_poll_kill(
ev_poll_t *poll,
void *thr);
76 HANDLE CompletionPort;
92io_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;
122error_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,
214io_poll_kill_func(ULONG_PTR Parameter)
216 *(BOOL *)(PVOID)Parameter = TRUE;
229 if (!thr.lpdwThreadId) {
231 dwThreadId = GetCurrentThreadId();
232 thr.lpdwThreadId = &dwThreadId;
239io_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);
301io_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);
328io_poll_from_svc(
const struct io_svc *svc)
void io_ctx_insert(io_ctx_t *ctx, struct io_svc *svc)
Registers an I/O service with an I/O context.
#define IO_SVC_INIT(vptr)
The static initializer for io_svc.
void io_ctx_remove(io_ctx_t *ctx, struct io_svc *svc)
Unregisters an I/O service with an I/O context.
This header file is part of the utilities library; it contains the native and platform-independent er...
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
const struct ev_poll_vtbl *const ev_poll_t
The abstract polling interface.
#define _Thread_local
An object whose identifier is declared with the storage-class specifier _Thread_local has thread stor...
This is the public header file of the utilities library.
#define structof(ptr, type, member)
Obtains the address of a structure from the address of one of its members.
ev_poll_t * io_poll_get_poll(const io_poll_t *poll)
Returns a pointer to the ev_poll_t instance corresponding to the I/O polling instance.
io_ctx_t * io_poll_get_ctx(const io_poll_t *poll)
Returns a pointer to the I/O context with which the I/O polling instance is registered.
This header file is part of the I/O library; it contains the I/O polling declarations for Windows.
int io_poll_register_handle(io_poll_t *poll, HANDLE handle)
Registers a file handle with (the I/O completion port of) an I/O polling instance.
int io_poll_post(io_poll_t *poll, size_t nbytes, struct io_cp *cp)
Posts a completion packet to the I/O completion port of an I/O polling instance.
void io_poll_destroy(io_poll_t *poll)
Destroys an I/O polling interface.
io_poll_t * io_poll_create(void)
Creates a new I/O polling interface.
This is the internal header file of the Windows-specific I/O declarations.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib....
An I/O polling interface.
An I/O completion packet.
io_cp_func_t * func
A pointer to the function to be invoked when the I/O operation completes.
OVERLAPPED overlapped
The OVERLAPPED structure submitted to the asynchronous I/O operation.
The virtual table of an I/O service.
This header file is part of the event library; it contains the task declarations.