Merge pull request #57 from vibe-d/fix_windows_completion_routines
Call Windows IO callbacks outside of completion routines.
This commit is contained in:
commit
acc35e1107
|
@ -4,6 +4,7 @@ version (Windows):
|
||||||
|
|
||||||
import eventcore.driver;
|
import eventcore.driver;
|
||||||
import eventcore.drivers.timer;
|
import eventcore.drivers.timer;
|
||||||
|
import eventcore.internal.consumablequeue;
|
||||||
import eventcore.internal.win32;
|
import eventcore.internal.win32;
|
||||||
import core.time : Duration;
|
import core.time : Duration;
|
||||||
import taggedalgebraic;
|
import taggedalgebraic;
|
||||||
|
@ -19,6 +20,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
HANDLE[] m_registeredEvents;
|
HANDLE[] m_registeredEvents;
|
||||||
void delegate() @safe nothrow[HANDLE] m_eventCallbacks;
|
void delegate() @safe nothrow[HANDLE] m_eventCallbacks;
|
||||||
HANDLE m_fileCompletionEvent;
|
HANDLE m_fileCompletionEvent;
|
||||||
|
ConsumableQueue!IOEvent m_ioEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
package {
|
package {
|
||||||
|
@ -31,6 +33,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
m_tid = () @trusted { return GetCurrentThreadId(); } ();
|
m_tid = () @trusted { return GetCurrentThreadId(); } ();
|
||||||
m_fileCompletionEvent = () @trusted { return CreateEventW(null, false, false, null); } ();
|
m_fileCompletionEvent = () @trusted { return CreateEventW(null, false, false, null); } ();
|
||||||
registerEvent(m_fileCompletionEvent);
|
registerEvent(m_fileCompletionEvent);
|
||||||
|
m_ioEvents = new ConsumableQueue!IOEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; }
|
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,
|
auto ret = () @trusted { return MsgWaitForMultipleObjectsEx(cast(DWORD)m_registeredEvents.length, m_registeredEvents.ptr,
|
||||||
timeout_msecs, QS_ALLEVENTS, MWMO_ALERTABLE|MWMO_INPUTAVAILABLE); } ();
|
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;
|
if (ret == WAIT_IO_COMPLETION) got_event = true;
|
||||||
else if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + m_registeredEvents.length) {
|
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) {
|
if (auto pc = m_registeredEvents[ret - WAIT_OBJECT_0] in m_eventCallbacks) {
|
||||||
|
@ -219,7 +225,7 @@ private struct HandleSlot {
|
||||||
|
|
||||||
package struct FileSlot {
|
package struct FileSlot {
|
||||||
static struct Direction(bool RO) {
|
static struct Direction(bool RO) {
|
||||||
OVERLAPPED_FILE overlapped;
|
OVERLAPPED_CORE overlapped;
|
||||||
FileIOCallback callback;
|
FileIOCallback callback;
|
||||||
ulong offset;
|
ulong offset;
|
||||||
size_t bytesTransferred;
|
size_t bytesTransferred;
|
||||||
|
@ -232,7 +238,7 @@ package struct FileSlot {
|
||||||
auto cb = this.callback;
|
auto cb = this.callback;
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
assert(cb !is 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;
|
Direction!false read;
|
||||||
|
@ -241,14 +247,28 @@ package struct FileSlot {
|
||||||
|
|
||||||
package struct WatcherSlot {
|
package struct WatcherSlot {
|
||||||
ubyte[] buffer;
|
ubyte[] buffer;
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED_CORE overlapped;
|
||||||
string directory;
|
string directory;
|
||||||
bool recursive;
|
bool recursive;
|
||||||
FileChangesCallback callback;
|
FileChangesCallback callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
package struct OVERLAPPED_FILE {
|
package struct OVERLAPPED_CORE {
|
||||||
OVERLAPPED overlapped;
|
OVERLAPPED overlapped;
|
||||||
|
alias overlapped this;
|
||||||
WinAPIEventDriverCore driver;
|
WinAPIEventDriverCore driver;
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
auto s = m_core.setupSlot!FileSlot(handle);
|
auto s = m_core.setupSlot!FileSlot(handle);
|
||||||
|
|
||||||
s.read.overlapped.driver = m_core;
|
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.driver = m_core;
|
||||||
s.write.overlapped.handle = FileFD(cast(size_t)handle);
|
s.write.overlapped.hEvent = handle;
|
||||||
|
|
||||||
return FileFD(cast(size_t)handle);
|
return FileFD(cast(size_t)handle);
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,9 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
{
|
{
|
||||||
auto h = idToHandle(file);
|
auto h = idToHandle(file);
|
||||||
auto slot = () @trusted { return &m_core.m_handles[h].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);
|
CloseHandle(h);
|
||||||
slot.read.overlapped.handle = slot.write.overlapped.handle = FileFD.invalid;
|
slot.read.overlapped.hEvent = slot.write.overlapped.hEvent = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,8 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nbytes = min(slot.buffer.length, DWORD.max);
|
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.overlapped.driver.removeWaiter();
|
||||||
slot.invokeCallback(IOStatus.error, slot.bytesTransferred);
|
slot.invokeCallback(IOStatus.error, slot.bytesTransferred);
|
||||||
}
|
}
|
||||||
|
@ -181,16 +182,15 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static extern(Windows)
|
private static nothrow
|
||||||
void onIOFinished(alias fun, bool RO)(DWORD error, DWORD bytes_transferred, OVERLAPPED* _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 = cast(FileFD)cast(size_t)overlapped.hEvent;
|
||||||
FileFD id = ctx.handle;
|
|
||||||
auto handle = idToHandle(id);
|
auto handle = idToHandle(id);
|
||||||
static if (RO)
|
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
|
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);
|
assert(slot !is null);
|
||||||
|
|
||||||
if (!slot.callback) {
|
if (!slot.callback) {
|
||||||
|
@ -199,7 +199,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
ctx.driver.removeWaiter();
|
overlapped.driver.removeWaiter();
|
||||||
slot.invokeCallback(IOStatus.error, slot.bytesTransferred + bytes_transferred);
|
slot.invokeCallback(IOStatus.error, slot.bytesTransferred + bytes_transferred);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
slot.offset += bytes_transferred;
|
slot.offset += bytes_transferred;
|
||||||
|
|
||||||
if (slot.bytesTransferred >= slot.buffer.length || slot.mode != IOMode.all) {
|
if (slot.bytesTransferred >= slot.buffer.length || slot.mode != IOMode.all) {
|
||||||
ctx.driver.removeWaiter();
|
overlapped.driver.removeWaiter();
|
||||||
slot.invokeCallback(IOStatus.ok, slot.bytesTransferred);
|
slot.invokeCallback(IOStatus.ok, slot.bytesTransferred);
|
||||||
} else {
|
} else {
|
||||||
startIO!(fun, RO)(handle, slot);
|
startIO!(fun, RO)(handle, slot);
|
||||||
|
|
|
@ -111,12 +111,13 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
//uint enable = 1;
|
//uint enable = 1;
|
||||||
//() @trusted { ioctlsocket(socket, FIONBIO, &enable); } ();
|
//() @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.Internal = 0;
|
||||||
overlapped.InternalHigh = 0;
|
overlapped.InternalHigh = 0;
|
||||||
overlapped.Offset = 0;
|
overlapped.Offset = 0;
|
||||||
overlapped.OffsetHigh = 0;
|
overlapped.OffsetHigh = 0;
|
||||||
overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket];
|
overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket];
|
||||||
|
overlapped.driver = m_core;
|
||||||
}
|
}
|
||||||
|
|
||||||
initSocketSlot(fd);
|
initSocketSlot(fd);
|
||||||
|
@ -226,9 +227,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
slot.read.wsabuf[0].len = buffer.length;
|
slot.read.wsabuf[0].len = buffer.length;
|
||||||
slot.read.wsabuf[0].buf = () @trusted { return buffer.ptr; } ();
|
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;
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -247,8 +249,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static extern(System) nothrow
|
private static nothrow
|
||||||
void onIOReadCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags)
|
void onIOReadCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped)
|
||||||
{
|
{
|
||||||
auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } ();
|
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].len = slot.streamSocket.read.buffer.length;
|
||||||
slot.streamSocket.read.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.read.buffer.ptr; } ();
|
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;
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -301,8 +304,9 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
slot.write.wsabuf[0].len = buffer.length;
|
slot.write.wsabuf[0].len = buffer.length;
|
||||||
slot.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)buffer.ptr; } ();
|
slot.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)buffer.ptr; } ();
|
||||||
|
|
||||||
auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped;
|
auto ovl = mode == IOMode.immediate ? null : &m_sockets[socket].streamSocket.write.overlapped.overlapped;
|
||||||
auto ret = () @trusted { return WSASend(socket, &slot.write.wsabuf[0], slot.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } ();
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -320,8 +324,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
m_core.addWaiter();
|
m_core.addWaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static extern(System) nothrow
|
private static nothrow
|
||||||
void onIOWriteCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags)
|
void onIOWriteCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped)
|
||||||
{
|
{
|
||||||
auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } ();
|
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].len = slot.streamSocket.write.buffer.length;
|
||||||
slot.streamSocket.write.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.streamSocket.write.buffer.ptr; } ();
|
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 ovl = slot.streamSocket.write.mode == IOMode.immediate ? null : &slot.streamSocket.write.overlapped.overlapped;
|
||||||
auto ret = () @trusted { return WSASend(slot.common.fd, &slot.streamSocket.write.wsabuf[0], slot.streamSocket.write.wsabuf.length, null, 0, ovl, &onIOWriteCompleted); } ();
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -431,12 +436,13 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
if (m_sockets[fd].common.refCount) // FD already in use?
|
if (m_sockets[fd].common.refCount) // FD already in use?
|
||||||
return DatagramSocketFD.invalid;
|
return DatagramSocketFD.invalid;
|
||||||
|
|
||||||
void setupOverlapped(ref WSAOVERLAPPEDX overlapped) @trusted @nogc nothrow {
|
void setupOverlapped(ref OVERLAPPED_CORE overlapped) @trusted @nogc nothrow {
|
||||||
overlapped.Internal = 0;
|
overlapped.Internal = 0;
|
||||||
overlapped.InternalHigh = 0;
|
overlapped.InternalHigh = 0;
|
||||||
overlapped.Offset = 0;
|
overlapped.Offset = 0;
|
||||||
overlapped.OffsetHigh = 0;
|
overlapped.OffsetHigh = 0;
|
||||||
overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket];
|
overlapped.hEvent = cast(HANDLE)cast(void*)&m_sockets[socket];
|
||||||
|
overlapped.driver = m_core;
|
||||||
}
|
}
|
||||||
|
|
||||||
initSocketSlot(fd);
|
initSocketSlot(fd);
|
||||||
|
@ -500,9 +506,10 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
slot.read.mode = mode;
|
slot.read.mode = mode;
|
||||||
slot.sourceAddrLen = DatagramSocketSlot.sourceAddr.sizeof;
|
slot.sourceAddrLen = DatagramSocketSlot.sourceAddr.sizeof;
|
||||||
|
|
||||||
auto ovl = &slot.read.overlapped;
|
auto ovl = &slot.read.overlapped.overlapped;
|
||||||
DWORD flags = 0;
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err != WSA_IO_PENDING) {
|
if (err != WSA_IO_PENDING) {
|
||||||
|
@ -527,8 +534,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
m_core.removeWaiter();
|
m_core.removeWaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static extern(System) nothrow
|
private static nothrow
|
||||||
void onIOReceiveCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags)
|
void onIOReceiveCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped)
|
||||||
{
|
{
|
||||||
auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } ();
|
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].len = slot.datagramSocket.read.buffer.length;
|
||||||
slot.datagramSocket.read.wsabuf[0].buf = () @trusted { return cast(ubyte*)slot.datagramSocket.read.buffer.ptr; } ();
|
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;
|
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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -588,10 +596,11 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
slot.write.mode = mode;
|
slot.write.mode = mode;
|
||||||
slot.targetAddr = target_address;
|
slot.targetAddr = target_address;
|
||||||
|
|
||||||
auto ovl = &slot.write.overlapped;
|
auto ovl = &slot.write.overlapped.overlapped;
|
||||||
auto tan = target_address ? target_address.name : null;
|
auto tan = target_address ? target_address.name : null;
|
||||||
auto tal = target_address ? target_address.nameLen : 0;
|
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) {
|
if (ret != 0) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
|
@ -617,8 +626,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
m_core.removeWaiter();
|
m_core.removeWaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static extern(System) nothrow
|
private static nothrow
|
||||||
void onIOSendCompleted(DWORD dwError, DWORD cbTransferred, WSAOVERLAPPEDX* lpOverlapped, DWORD dwFlags)
|
void onIOSendCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* lpOverlapped)
|
||||||
{
|
{
|
||||||
auto slot = () @trusted { return cast(SocketVector.FullField*)lpOverlapped.hEvent; } ();
|
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; } ();
|
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 tan = slot.datagramSocket.targetAddr ? slot.datagramSocket.targetAddr.name : null;
|
||||||
auto tal = slot.datagramSocket.targetAddr ? slot.datagramSocket.targetAddr.nameLen : 0;
|
auto tal = slot.datagramSocket.targetAddr ? slot.datagramSocket.targetAddr.nameLen : 0;
|
||||||
auto ovl = slot.datagramSocket.write.mode == IOMode.immediate ? null : &slot.datagramSocket.write.overlapped;
|
auto ovl = slot.datagramSocket.write.mode == IOMode.immediate ? null : &slot.datagramSocket.write.overlapped.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 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) {
|
if (ret == SOCKET_ERROR) {
|
||||||
auto err = WSAGetLastError();
|
auto err = WSAGetLastError();
|
||||||
if (err == WSA_IO_PENDING) {
|
if (err == WSA_IO_PENDING) {
|
||||||
|
@ -878,7 +888,7 @@ private struct StreamSocketSlot {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct StreamDirection(bool RO) {
|
static struct StreamDirection(bool RO) {
|
||||||
WSAOVERLAPPEDX overlapped;
|
OVERLAPPED_CORE overlapped;
|
||||||
static if (RO) const(ubyte)[] buffer;
|
static if (RO) const(ubyte)[] buffer;
|
||||||
else ubyte[] buffer;
|
else ubyte[] buffer;
|
||||||
WSABUF[1] wsabuf;
|
WSABUF[1] wsabuf;
|
||||||
|
@ -902,7 +912,7 @@ private struct DatagramSocketSlot {
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct DgramDirection(bool RO) {
|
static struct DgramDirection(bool RO) {
|
||||||
WSAOVERLAPPEDX overlapped;
|
OVERLAPPED_CORE overlapped;
|
||||||
static if (RO) const(ubyte)[] buffer;
|
static if (RO) const(ubyte)[] buffer;
|
||||||
else ubyte[] buffer;
|
else ubyte[] buffer;
|
||||||
WSABUF[1] wsabuf;
|
WSABUF[1] wsabuf;
|
||||||
|
|
|
@ -41,6 +41,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
|
||||||
slot.directory = path;
|
slot.directory = path;
|
||||||
slot.recursive = recursive;
|
slot.recursive = recursive;
|
||||||
slot.callback = callback;
|
slot.callback = callback;
|
||||||
|
slot.overlapped.driver = m_core;
|
||||||
slot.buffer = () @trusted {
|
slot.buffer = () @trusted {
|
||||||
try return theAllocator.makeArray!ubyte(16384);
|
try return theAllocator.makeArray!ubyte(16384);
|
||||||
catch (Exception e) assert(false, "Failed to allocate directory watcher buffer.");
|
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
|
// the current wait operation. Simply cancel the I/O to let the
|
||||||
// completion callback
|
// completion callback
|
||||||
if (slot.refCount == 1) {
|
if (slot.refCount == 1) {
|
||||||
() @trusted { CancelIoEx(handle, &slot.watcher.overlapped); } ();
|
() @trusted { CancelIoEx(handle, &slot.watcher.overlapped.overlapped); } ();
|
||||||
slot.watcher.callback = null;
|
slot.watcher.callback = null;
|
||||||
core.removeWaiter();
|
core.removeWaiter();
|
||||||
}
|
}
|
||||||
|
@ -99,8 +100,8 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static nothrow extern(System)
|
private static nothrow
|
||||||
void onIOCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED* overlapped)
|
void onIOCompleted(DWORD dwError, DWORD cbTransferred, OVERLAPPED_CORE* overlapped)
|
||||||
{
|
{
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
import std.file : isDir;
|
import std.file : isDir;
|
||||||
|
@ -176,9 +177,10 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
|
||||||
slot.overlapped.hEvent = handle;
|
slot.overlapped.hEvent = handle;
|
||||||
|
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
auto handler = &overlappedIOHandler!onIOCompleted;
|
||||||
() @trusted {
|
() @trusted {
|
||||||
ret = ReadDirectoryChangesW(handle, slot.buffer.ptr, cast(DWORD)slot.buffer.length, slot.recursive,
|
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) {
|
if (!ret) {
|
||||||
|
|
|
@ -30,6 +30,8 @@ enum {
|
||||||
MAX_PROTOCOL_CHAIN = 7,
|
MAX_PROTOCOL_CHAIN = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum WSAEDISCON = 10101;
|
||||||
|
|
||||||
enum WSA_OPERATION_ABORTED = 995;
|
enum WSA_OPERATION_ABORTED = 995;
|
||||||
enum WSA_IO_PENDING = 997;
|
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 TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, OVERLAPPED* lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags);
|
||||||
BOOL CancelIoEx(HANDLE hFile, LPOVERLAPPED lpOverlapped);
|
BOOL CancelIoEx(HANDLE hFile, LPOVERLAPPED lpOverlapped);
|
||||||
|
|
||||||
struct WSAOVERLAPPEDX {
|
/*struct WSAOVERLAPPEDX {
|
||||||
ULONG_PTR Internal;
|
ULONG_PTR Internal;
|
||||||
ULONG_PTR InternalHigh;
|
ULONG_PTR InternalHigh;
|
||||||
union {
|
union {
|
||||||
|
@ -164,4 +166,6 @@ struct WSAOVERLAPPEDX {
|
||||||
PVOID Pointer;
|
PVOID Pointer;
|
||||||
}
|
}
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
alias WSAOVERLAPPEDX = OVERLAPPED;
|
||||||
|
|
Loading…
Reference in a new issue