From 0e1d74cc41bc573270c7f53a3c274fbe44daf05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Sat, 10 Mar 2018 22:59:21 +0100 Subject: [PATCH 1/2] Call Windows IO callbacks outside of completion routines. Calling WinSock functions from inside of a completion routine results in undefined behavior, because the completion routine may be triggered within another WinSock function that enters an alertable wait state. For this reason, none of the callbacks that are triggered by overlapped I/O may be invoked directly from a completion routine. To solve this, a ConsumableQueue is filled with all completion events that occur and is processed after each MsgWaitForMultipleObjectsEx call. --- source/eventcore/drivers/winapi/core.d | 30 +++++++++- source/eventcore/drivers/winapi/files.d | 7 ++- source/eventcore/drivers/winapi/sockets.d | 66 +++++++++++++--------- source/eventcore/drivers/winapi/watchers.d | 10 ++-- source/eventcore/internal/win32.d | 8 ++- 5 files changed, 82 insertions(+), 39 deletions(-) diff --git a/source/eventcore/drivers/winapi/core.d b/source/eventcore/drivers/winapi/core.d index b3f4dde..ec5e2c5 100644 --- a/source/eventcore/drivers/winapi/core.d +++ b/source/eventcore/drivers/winapi/core.d @@ -4,6 +4,7 @@ version (Windows): import eventcore.driver; import eventcore.drivers.timer; +import eventcore.internal.consumablequeue; import eventcore.internal.win32; import core.time : Duration; import taggedalgebraic; @@ -19,6 +20,7 @@ final class WinAPIEventDriverCore : EventDriverCore { HANDLE[] m_registeredEvents; void delegate() @safe nothrow[HANDLE] m_eventCallbacks; HANDLE m_fileCompletionEvent; + ConsumableQueue!IOEvent m_ioEvents; } package { @@ -31,6 +33,7 @@ final class WinAPIEventDriverCore : EventDriverCore { m_tid = () @trusted { return GetCurrentThreadId(); } (); m_fileCompletionEvent = () @trusted { return CreateEventW(null, false, false, null); } (); registerEvent(m_fileCompletionEvent); + m_ioEvents = new ConsumableQueue!IOEvent; } override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; } @@ -116,6 +119,9 @@ final class WinAPIEventDriverCore : EventDriverCore { auto ret = () @trusted { return MsgWaitForMultipleObjectsEx(cast(DWORD)m_registeredEvents.length, m_registeredEvents.ptr, timeout_msecs, QS_ALLEVENTS, MWMO_ALERTABLE|MWMO_INPUTAVAILABLE); } (); + foreach (evt; m_ioEvents.consume) + evt.process(evt.error, evt.bytesTransferred, evt.overlapped); + if (ret == WAIT_IO_COMPLETION) got_event = true; else if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + m_registeredEvents.length) { if (auto pc = m_registeredEvents[ret - WAIT_OBJECT_0] in m_eventCallbacks) { @@ -241,14 +247,34 @@ package struct FileSlot { package struct WatcherSlot { ubyte[] buffer; - OVERLAPPED overlapped; + OVERLAPPED_CORE overlapped; string directory; bool recursive; FileChangesCallback callback; } -package struct OVERLAPPED_FILE { +package struct OVERLAPPED_CORE { OVERLAPPED overlapped; + alias overlapped this; WinAPIEventDriverCore driver; +} + +package struct OVERLAPPED_FILE { + OVERLAPPED_CORE core; + alias core this; FileFD handle; } + +package struct IOEvent { + void function(DWORD err, DWORD bts, OVERLAPPED_CORE*) @safe nothrow process; + DWORD error; + DWORD bytesTransferred; + OVERLAPPED_CORE* overlapped; +} + +package extern(System) @system nothrow +void overlappedIOHandler(alias process, EXTRA...)(DWORD error, DWORD bytes_transferred, OVERLAPPED* _overlapped, EXTRA extra) +{ + auto overlapped = cast(OVERLAPPED_CORE*)_overlapped; + overlapped.driver.m_ioEvents.put(IOEvent(&process, error, bytes_transferred, overlapped)); +} diff --git a/source/eventcore/drivers/winapi/files.d b/source/eventcore/drivers/winapi/files.d index 5f42f8d..720aa7b 100644 --- a/source/eventcore/drivers/winapi/files.d +++ b/source/eventcore/drivers/winapi/files.d @@ -165,7 +165,8 @@ final class WinAPIEventDriverFiles : EventDriverFiles { } auto nbytes = min(slot.buffer.length, DWORD.max); - if (!() @trusted { return fun(h, &slot.buffer[0], nbytes, &slot.overlapped.overlapped, &onIOFinished!(fun, RO)); } ()) { + auto handler = &overlappedIOHandler!(onIOFinished!(fun, RO)); + if (!() @trusted { return fun(h, &slot.buffer[0], nbytes, &slot.overlapped.overlapped, handler); } ()) { slot.overlapped.driver.removeWaiter(); slot.invokeCallback(IOStatus.error, slot.bytesTransferred); } @@ -181,8 +182,8 @@ final class WinAPIEventDriverFiles : EventDriverFiles { } } - private static extern(Windows) - void onIOFinished(alias fun, bool RO)(DWORD error, DWORD bytes_transferred, OVERLAPPED* _overlapped) + private static nothrow + void onIOFinished(alias fun, bool RO)(DWORD error, DWORD bytes_transferred, OVERLAPPED_CORE* _overlapped) { auto ctx = () @trusted { return cast(OVERLAPPED_FILE*)_overlapped; } (); FileFD id = ctx.handle; diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index ebf6e9e..22ed186 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -111,12 +111,13 @@ final class WinAPIEventDriverSockets : EventDriverSockets { //uint enable = 1; //() @trusted { ioctlsocket(socket, FIONBIO, &enable); } (); - void setupOverlapped(ref WSAOVERLAPPEDX overlapped) @trusted @nogc nothrow { + void setupOverlapped(ref OVERLAPPED_CORE overlapped) @trusted @nogc nothrow { overlapped.Internal = 0; overlapped.InternalHigh = 0; overlapped.Offset = 0; overlapped.OffsetHigh = 0; overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket]; + overlapped.driver = m_core; } initSocketSlot(fd); @@ -226,9 +227,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.read.wsabuf[0].len = buffer.length; slot.read.wsabuf[0].buf = () @trusted { return buffer.ptr; } (); - auto ovl = mode == IOMode.immediate ? null : &slot.read.overlapped; + auto ovl = mode == IOMode.immediate ? null : &slot.read.overlapped.overlapped; DWORD flags = 0; - auto ret = () @trusted { return WSARecv(socket, &slot.read.wsabuf[0], slot.read.wsabuf.length, null, &flags, ovl, &onIOReadCompleted); } (); + auto handler = &overlappedIOHandler!(onIOReadCompleted, DWORD); + auto ret = () @trusted { return WSARecv(socket, &slot.read.wsabuf[0], slot.read.wsabuf.length, null, &flags, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -247,8 +249,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } - private static extern(System) nothrow - void onIOReadCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags) + private static nothrow + void onIOReadCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped) { auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } (); @@ -278,9 +280,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.streamSocket.read.wsabuf[0].len = slot.streamSocket.read.buffer.length; slot.streamSocket.read.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.read.buffer.ptr; } (); - auto ovl = slot.streamSocket.read.mode == IOMode.immediate ? null : &slot.streamSocket.read.overlapped; + auto ovl = slot.streamSocket.read.mode == IOMode.immediate ? null : &slot.streamSocket.read.overlapped.overlapped; DWORD flags = 0; - auto ret = () @trusted { return WSARecv(slot.common.fd, &slot.streamSocket.read.wsabuf[0], slot.streamSocket.read.wsabuf.length, null, &flags, ovl, &onIOReadCompleted); } (); + auto handler = &overlappedIOHandler!(onIOReadCompleted, DWORD); + auto ret = () @trusted { return WSARecv(slot.common.fd, &slot.streamSocket.read.wsabuf[0], slot.streamSocket.read.wsabuf.length, null, &flags, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -301,8 +304,9 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.write.wsabuf[0].len = buffer.length; slot.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)buffer.ptr; } (); - auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped; - auto ret = () @trusted { return WSASend(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } (); + auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped.overlapped; + auto handler = &overlappedIOHandler!(onIOWriteCompleted, DWORD); + auto ret = () @trusted { return WSASend(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -320,8 +324,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { m_core.addWaiter(); } - private static extern(System) nothrow - void onIOWriteCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags) + private static nothrow + void onIOWriteCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped) { auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } (); @@ -351,8 +355,9 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.streamSocket.write.wsabuf[0].len = slot.streamSocket.write.buffer.length; slot.streamSocket.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.write.buffer.ptr; } (); - auto ovl = slot.streamSocket.write.mode == IOMode.immediate ? null : &slot.streamSocket.write.overlapped; - auto ret = () @trusted { return WSASend(slot.common.fd, &slot.streamSocket.write.wsabuf[0], slot.streamSocket.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } (); + auto ovl = slot.streamSocket.write.mode == IOMode.immediate ? null : &slot.streamSocket.write.overlapped.overlapped; + auto handler = &overlappedIOHandler!(onIOWriteCompleted, DWORD); + auto ret = () @trusted { return WSASend(slot.common.fd, &slot.streamSocket.write.wsabuf[0], slot.streamSocket.write.wsabuf.length, null, 0, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -431,12 +436,13 @@ final class WinAPIEventDriverSockets : EventDriverSockets { if (m_sockets[fd].common.refCount) // FD already in use? return DatagramSocketFD.invalid; - void setupOverlapped(ref WSAOVERLAPPEDX overlapped) @trusted @nogc nothrow { + void setupOverlapped(ref OVERLAPPED_CORE overlapped) @trusted @nogc nothrow { overlapped.Internal = 0; overlapped.InternalHigh = 0; overlapped.Offset = 0; overlapped.OffsetHigh = 0; overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket]; + overlapped.driver = m_core; } initSocketSlot(fd); @@ -500,9 +506,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.read.mode = mode; slot.sourceAddrLen = DatagramSocketSlot.sourceAddr.sizeof; - auto ovl = &slot.read.overlapped; + auto ovl = &slot.read.overlapped.overlapped; DWORD flags = 0; - auto ret = () @trusted { return WSARecvFrom(socket, &slot.read.wsabuf[0], slot.read.wsabuf.length, null, &flags, cast(SOCKADDR*)&slot.sourceAddr, &slot.sourceAddrLen, ovl, &onIOReceiveCompleted); } (); + auto handler = &overlappedIOHandler!(onIOReceiveCompleted, DWORD); + auto ret = () @trusted { return WSARecvFrom(socket, &slot.read.wsabuf[0], slot.read.wsabuf.length, null, &flags, cast(SOCKADDR*)&slot.sourceAddr, &slot.sourceAddrLen, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err != WSA_IO_PENDING) { @@ -527,8 +534,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { m_core.removeWaiter(); } - private static extern(System) nothrow - void onIOReceiveCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags) + private static nothrow + void onIOReceiveCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped) { auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } (); @@ -564,9 +571,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.datagramSocket.read.wsabuf[0].len = slot.datagramSocket.read.buffer.length; slot.datagramSocket.read.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.datagramSocket.read.buffer.ptr; } (); - auto ovl = slot.datagramSocket.read.mode == IOMode.immediate ? null : &slot.datagramSocket.read.overlapped; + auto ovl = slot.datagramSocket.read.mode == IOMode.immediate ? null : &slot.datagramSocket.read.overlapped.overlapped; DWORD flags = 0; - auto ret = () @trusted { return WSARecvFrom(slot.common.fd, &slot.datagramSocket.read.wsabuf[0], slot.datagramSocket.read.wsabuf.length, null, &flags, cast(SOCKADDR*)&slot.datagramSocket.sourceAddr, &slot.datagramSocket.sourceAddrLen, ovl, &onIOReceiveCompleted); } (); + auto handler = &overlappedIOHandler!(onIOReceiveCompleted, DWORD); + auto ret = () @trusted { return WSARecvFrom(slot.common.fd, &slot.datagramSocket.read.wsabuf[0], slot.datagramSocket.read.wsabuf.length, null, &flags, cast(SOCKADDR*)&slot.datagramSocket.sourceAddr, &slot.datagramSocket.sourceAddrLen, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -588,10 +596,11 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.write.mode = mode; slot.targetAddr = target_address; - auto ovl = &slot.write.overlapped; + auto ovl = &slot.write.overlapped.overlapped; auto tan = target_address ? target_address.name : null; auto tal = target_address ? target_address.nameLen : 0; - auto ret = () @trusted { return WSASendTo(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, tan, tal, ovl, &onIOSendCompleted); } (); + auto handler = &overlappedIOHandler!(onIOSendCompleted, DWORD); + auto ret = () @trusted { return WSASendTo(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, tan, tal, ovl, handler); } (); if (ret != 0) { auto err = WSAGetLastError(); @@ -617,8 +626,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { m_core.removeWaiter(); } - private static extern(System) nothrow - void onIOSendCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags) + private static nothrow + void onIOSendCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped) { auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } (); @@ -664,8 +673,9 @@ final class WinAPIEventDriverSockets : EventDriverSockets { slot.datagramSocket.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.datagramSocket.write.buffer.ptr; } (); auto tan = slot.datagramSocket.targetAddr ? slot.datagramSocket.targetAddr.name : null; auto tal = slot.datagramSocket.targetAddr ? slot.datagramSocket.targetAddr.nameLen : 0; - auto ovl = slot.datagramSocket.write.mode == IOMode.immediate ? null : &slot.datagramSocket.write.overlapped; - auto ret = () @trusted { return WSASendTo(slot.common.fd, &slot.datagramSocket.write.wsabuf[0], slot.datagramSocket.write.wsabuf.length, null, 0, tan, tal, ovl, &onIOSendCompleted); } (); + auto ovl = slot.datagramSocket.write.mode == IOMode.immediate ? null : &slot.datagramSocket.write.overlapped.overlapped; + auto handler = &overlappedIOHandler!(onIOSendCompleted, DWORD); + auto ret = () @trusted { return WSASendTo(slot.common.fd, &slot.datagramSocket.write.wsabuf[0], slot.datagramSocket.write.wsabuf.length, null, 0, tan, tal, ovl, handler); } (); if (ret == SOCKET_ERROR) { auto err = WSAGetLastError(); if (err == WSA_IO_PENDING) { @@ -878,7 +888,7 @@ private struct StreamSocketSlot { } static struct StreamDirection(bool RO) { - WSAOVERLAPPEDX overlapped; + OVERLAPPED_CORE overlapped; static if (RO) const(ubyte)[] buffer; else ubyte[] buffer; WSABUF[1] wsabuf; @@ -902,7 +912,7 @@ private struct DatagramSocketSlot { } static struct DgramDirection(bool RO) { - WSAOVERLAPPEDX overlapped; + OVERLAPPED_CORE overlapped; static if (RO) const(ubyte)[] buffer; else ubyte[] buffer; WSABUF[1] wsabuf; diff --git a/source/eventcore/drivers/winapi/watchers.d b/source/eventcore/drivers/winapi/watchers.d index b4e9467..524af9d 100644 --- a/source/eventcore/drivers/winapi/watchers.d +++ b/source/eventcore/drivers/winapi/watchers.d @@ -41,6 +41,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { slot.directory = path; slot.recursive = recursive; slot.callback = callback; + slot.overlapped.driver = m_core; slot.buffer = () @trusted { try return theAllocator.makeArray!ubyte(16384); catch (Exception e) assert(false, "Failed to allocate directory watcher buffer."); @@ -91,7 +92,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { // the current wait operation. Simply cancel the I/O to let the // completion callback if (slot.refCount == 1) { - () @trusted { CancelIoEx(handle, &slot.watcher.overlapped); } (); + () @trusted { CancelIoEx(handle, &slot.watcher.overlapped.overlapped); } (); slot.watcher.callback = null; core.removeWaiter(); } @@ -99,8 +100,8 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { return true; } - private static nothrow extern(System) - void onIOCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED* overlapped) + private static nothrow + void onIOCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* overlapped) { import std.conv : to; import std.file : isDir; @@ -176,9 +177,10 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { slot.overlapped.hEvent = handle; BOOL ret; + auto handler = &overlappedIOHandler!onIOCompleted; () @trusted { ret = ReadDirectoryChangesW(handle, slot.buffer.ptr, cast(DWORD)slot.buffer.length, slot.recursive, - notifications, null, &slot.overlapped, &onIOCompleted); + notifications, null, &slot.overlapped.overlapped, handler); } (); if (!ret) { diff --git a/source/eventcore/internal/win32.d b/source/eventcore/internal/win32.d index 9fad47f..af068b3 100644 --- a/source/eventcore/internal/win32.d +++ b/source/eventcore/internal/win32.d @@ -30,6 +30,8 @@ enum { MAX_PROTOCOL_CHAIN = 7, } +enum WSAEDISCON = 10101; + enum WSA_OPERATION_ABORTED = 995; enum WSA_IO_PENDING = 997; @@ -153,7 +155,7 @@ void freeaddrinfo(ADDRINFOA* ai); BOOL TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, OVERLAPPED* lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags); BOOL CancelIoEx(HANDLE hFile, LPOVERLAPPED lpOverlapped); -struct WSAOVERLAPPEDX { +/*struct WSAOVERLAPPEDX { ULONG_PTR Internal; ULONG_PTR InternalHigh; union { @@ -164,4 +166,6 @@ struct WSAOVERLAPPEDX { PVOID Pointer; } HANDLE hEvent; -} +}*/ + +alias WSAOVERLAPPEDX = OVERLAPPED; From 9dc8b796e59494af7d400a8f88e2e45927b098a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Sun, 11 Mar 2018 00:27:14 +0100 Subject: [PATCH 2/2] Get rid of OVERLAPPED_FILE. The hEvent member is currently unused for files. Using it for the file handle makes the OVERLAPPED_CORE struct sufficient. --- source/eventcore/drivers/winapi/core.d | 10 ++-------- source/eventcore/drivers/winapi/files.d | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/source/eventcore/drivers/winapi/core.d b/source/eventcore/drivers/winapi/core.d index ec5e2c5..f485e9f 100644 --- a/source/eventcore/drivers/winapi/core.d +++ b/source/eventcore/drivers/winapi/core.d @@ -225,7 +225,7 @@ private struct HandleSlot { package struct FileSlot { static struct Direction(bool RO) { - OVERLAPPED_FILE overlapped; + OVERLAPPED_CORE overlapped; FileIOCallback callback; ulong offset; size_t bytesTransferred; @@ -238,7 +238,7 @@ package struct FileSlot { auto cb = this.callback; this.callback = null; assert(cb !is null); - cb(overlapped.handle, status, bytes_transferred); + cb(cast(FileFD)cast(size_t)overlapped.hEvent, status, bytes_transferred); } } Direction!false read; @@ -259,12 +259,6 @@ package struct OVERLAPPED_CORE { WinAPIEventDriverCore driver; } -package struct OVERLAPPED_FILE { - OVERLAPPED_CORE core; - alias core this; - FileFD handle; -} - package struct IOEvent { void function(DWORD err, DWORD bts, OVERLAPPED_CORE*) @safe nothrow process; DWORD error; diff --git a/source/eventcore/drivers/winapi/files.d b/source/eventcore/drivers/winapi/files.d index 720aa7b..871e7ec 100644 --- a/source/eventcore/drivers/winapi/files.d +++ b/source/eventcore/drivers/winapi/files.d @@ -64,9 +64,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles { auto s = m_core.setupSlot!FileSlot(handle); s.read.overlapped.driver = m_core; - s.read.overlapped.handle = FileFD(cast(size_t)handle); + s.read.overlapped.hEvent = handle; s.write.overlapped.driver = m_core; - s.write.overlapped.handle = FileFD(cast(size_t)handle); + s.write.overlapped.hEvent = handle; return FileFD(cast(size_t)handle); } @@ -75,9 +75,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles { { auto h = idToHandle(file); auto slot = () @trusted { return &m_core.m_handles[h].file(); } (); - if (slot.read.overlapped.handle != FileFD.invalid) { + if (slot.read.overlapped.hEvent != INVALID_HANDLE_VALUE) { CloseHandle(h); - slot.read.overlapped.handle = slot.write.overlapped.handle = FileFD.invalid; + slot.read.overlapped.hEvent = slot.write.overlapped.hEvent = INVALID_HANDLE_VALUE; } } @@ -183,15 +183,14 @@ final class WinAPIEventDriverFiles : EventDriverFiles { } private static nothrow - void onIOFinished(alias fun, bool RO)(DWORD error, DWORD bytes_transferred, OVERLAPPED_CORE* _overlapped) + void onIOFinished(alias fun, bool RO)(DWORD error, DWORD bytes_transferred, OVERLAPPED_CORE* overlapped) { - auto ctx = () @trusted { return cast(OVERLAPPED_FILE*)_overlapped; } (); - FileFD id = ctx.handle; + FileFD id = cast(FileFD)cast(size_t)overlapped.hEvent; auto handle = idToHandle(id); static if (RO) - auto slot = () @trusted { return &ctx.driver.m_handles[handle].file.write; } (); + auto slot = () @trusted { return &overlapped.driver.m_handles[handle].file.write; } (); else - auto slot = () @trusted { return &ctx.driver.m_handles[handle].file.read; } (); + auto slot = () @trusted { return &overlapped.driver.m_handles[handle].file.read; } (); assert(slot !is null); if (!slot.callback) { @@ -200,7 +199,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles { } if (error != 0) { - ctx.driver.removeWaiter(); + overlapped.driver.removeWaiter(); slot.invokeCallback(IOStatus.error, slot.bytesTransferred + bytes_transferred); return; } @@ -209,7 +208,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles { slot.offset += bytes_transferred; if (slot.bytesTransferred >= slot.buffer.length || slot.mode != IOMode.all) { - ctx.driver.removeWaiter(); + overlapped.driver.removeWaiter(); slot.invokeCallback(IOStatus.ok, slot.bytesTransferred); } else { startIO!(fun, RO)(handle, slot);