Make the WinAPI driver initialization nogc.
This commit is contained in:
parent
e7e4a0f5f5
commit
284d4f43c3
|
@ -5,7 +5,7 @@ version (Windows):
|
||||||
import eventcore.driver;
|
import eventcore.driver;
|
||||||
import eventcore.drivers.timer;
|
import eventcore.drivers.timer;
|
||||||
import eventcore.internal.consumablequeue;
|
import eventcore.internal.consumablequeue;
|
||||||
import eventcore.internal.utils : nogc_assert;
|
import eventcore.internal.utils : mallocT, freeT, nogc_assert;
|
||||||
import eventcore.internal.win32;
|
import eventcore.internal.win32;
|
||||||
import core.sync.mutex : Mutex;
|
import core.sync.mutex : Mutex;
|
||||||
import core.time : Duration;
|
import core.time : Duration;
|
||||||
|
@ -21,8 +21,9 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
size_t m_waiterCount;
|
size_t m_waiterCount;
|
||||||
DWORD m_tid;
|
DWORD m_tid;
|
||||||
LoopTimeoutTimerDriver m_timers;
|
LoopTimeoutTimerDriver m_timers;
|
||||||
HANDLE[] m_registeredEvents;
|
HANDLE[MAXIMUM_WAIT_OBJECTS] m_registeredEvents;
|
||||||
void delegate() @safe nothrow[HANDLE] m_eventCallbacks;
|
void delegate() @safe nothrow[MAXIMUM_WAIT_OBJECTS] m_registeredEventCallbacks;
|
||||||
|
DWORD m_registeredEventCount = 0;
|
||||||
HANDLE m_fileCompletionEvent;
|
HANDLE m_fileCompletionEvent;
|
||||||
ConsumableQueue!IOEvent m_ioEvents;
|
ConsumableQueue!IOEvent m_ioEvents;
|
||||||
|
|
||||||
|
@ -35,27 +36,36 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
}
|
}
|
||||||
|
|
||||||
this(LoopTimeoutTimerDriver timers)
|
this(LoopTimeoutTimerDriver timers)
|
||||||
{
|
@nogc {
|
||||||
m_timers = timers;
|
m_timers = timers;
|
||||||
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;
|
m_ioEvents = mallocT!(ConsumableQueue!IOEvent);
|
||||||
|
|
||||||
static if (__VERSION__ >= 2074)
|
static if (__VERSION__ >= 2074)
|
||||||
m_threadCallbackMutex = new shared Mutex;
|
m_threadCallbackMutex = mallocT!(shared(Mutex));
|
||||||
else {
|
else {
|
||||||
() @trusted { m_threadCallbackMutex = cast(shared)new Mutex; } ();
|
() @trusted { m_threadCallbackMutex = cast(shared)mallocT!Mutex; } ();
|
||||||
}
|
}
|
||||||
m_threadCallbacks = new ConsumableQueue!(Tuple!(ThreadCallback, intptr_t));
|
m_threadCallbacks = mallocT!(ConsumableQueue!(Tuple!(ThreadCallback, intptr_t)));
|
||||||
m_threadCallbacks.reserve(1000);
|
m_threadCallbacks.reserve(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispose()
|
||||||
|
@trusted {
|
||||||
|
try {
|
||||||
|
freeT(m_threadCallbacks);
|
||||||
|
freeT(m_threadCallbackMutex);
|
||||||
|
freeT(m_ioEvents);
|
||||||
|
} catch (Exception e) assert(false, e.msg);
|
||||||
|
}
|
||||||
|
|
||||||
override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; }
|
override size_t waiterCount() { return m_waiterCount + m_timers.pendingCount; }
|
||||||
|
|
||||||
package void addWaiter() { m_waiterCount++; }
|
package void addWaiter() @nogc { m_waiterCount++; }
|
||||||
package void removeWaiter()
|
package void removeWaiter()
|
||||||
{
|
@nogc {
|
||||||
assert(m_waiterCount > 0, "Decrementing waiter count below zero.");
|
assert(m_waiterCount > 0, "Decrementing waiter count below zero.");
|
||||||
m_waiterCount--;
|
m_waiterCount--;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +169,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
bool got_event;
|
bool got_event;
|
||||||
|
|
||||||
DWORD timeout_msecs = max_wait == Duration.max ? INFINITE : cast(DWORD)min(max(max_wait.total!"msecs", 0), DWORD.max);
|
DWORD timeout_msecs = max_wait == Duration.max ? INFINITE : cast(DWORD)min(max(max_wait.total!"msecs", 0), DWORD.max);
|
||||||
auto ret = () @trusted { return MsgWaitForMultipleObjectsEx(cast(DWORD)m_registeredEvents.length, m_registeredEvents.ptr,
|
auto ret = () @trusted { return MsgWaitForMultipleObjectsEx(m_registeredEventCount, m_registeredEvents.ptr,
|
||||||
timeout_msecs, QS_ALLEVENTS, MWMO_ALERTABLE|MWMO_INPUTAVAILABLE); } ();
|
timeout_msecs, QS_ALLEVENTS, MWMO_ALERTABLE|MWMO_INPUTAVAILABLE); } ();
|
||||||
|
|
||||||
while (!m_ioEvents.empty) {
|
while (!m_ioEvents.empty) {
|
||||||
|
@ -168,9 +178,9 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
}
|
}
|
||||||
|
|
||||||
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_registeredEventCount) {
|
||||||
if (auto pc = m_registeredEvents[ret - WAIT_OBJECT_0] in m_eventCallbacks) {
|
if (auto cb = m_registeredEventCallbacks[ret - WAIT_OBJECT_0]) {
|
||||||
(*pc)();
|
cb();
|
||||||
got_event = true;
|
got_event = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,9 +219,11 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
|
|
||||||
|
|
||||||
package void registerEvent(HANDLE event, void delegate() @safe nothrow callback = null)
|
package void registerEvent(HANDLE event, void delegate() @safe nothrow callback = null)
|
||||||
{
|
@nogc {
|
||||||
m_registeredEvents ~= event;
|
assert(m_registeredEventCount < MAXIMUM_WAIT_OBJECTS, "Too many registered events.");
|
||||||
if (callback) m_eventCallbacks[event] = callback;
|
m_registeredEvents[m_registeredEventCount] = event;
|
||||||
|
if (callback) m_registeredEventCallbacks[m_registeredEventCount] = callback;
|
||||||
|
m_registeredEventCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
package SlotType* setupSlot(SlotType)(HANDLE h)
|
package SlotType* setupSlot(SlotType)(HANDLE h)
|
||||||
|
@ -231,7 +243,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
|
||||||
}
|
}
|
||||||
|
|
||||||
package void discardEvents(scope OVERLAPPED_CORE*[] overlapped...)
|
package void discardEvents(scope OVERLAPPED_CORE*[] overlapped...)
|
||||||
{
|
@nogc {
|
||||||
import std.algorithm.searching : canFind;
|
import std.algorithm.searching : canFind;
|
||||||
m_ioEvents.filterPending!(evt => !overlapped.canFind(evt.overlapped));
|
m_ioEvents.filterPending!(evt => !overlapped.canFind(evt.overlapped));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import eventcore.drivers.winapi.files;
|
||||||
import eventcore.drivers.winapi.signals;
|
import eventcore.drivers.winapi.signals;
|
||||||
import eventcore.drivers.winapi.sockets;
|
import eventcore.drivers.winapi.sockets;
|
||||||
import eventcore.drivers.winapi.watchers;
|
import eventcore.drivers.winapi.watchers;
|
||||||
|
import eventcore.internal.utils : mallocT, freeT;
|
||||||
import core.sys.windows.windows;
|
import core.sys.windows.windows;
|
||||||
|
|
||||||
static assert(HANDLE.sizeof <= FD.BaseType.sizeof);
|
static assert(HANDLE.sizeof <= FD.BaseType.sizeof);
|
||||||
|
@ -39,23 +40,25 @@ final class WinAPIEventDriver : EventDriver {
|
||||||
static WinAPIEventDriver threadInstance;
|
static WinAPIEventDriver threadInstance;
|
||||||
|
|
||||||
this()
|
this()
|
||||||
@safe {
|
@safe nothrow @nogc {
|
||||||
assert(threadInstance is null);
|
assert(threadInstance is null);
|
||||||
threadInstance = this;
|
threadInstance = this;
|
||||||
|
|
||||||
import std.exception : enforce;
|
import std.exception : enforce;
|
||||||
|
|
||||||
WSADATA wd;
|
WSADATA wd;
|
||||||
enforce(() @trusted { return WSAStartup(0x0202, &wd); } () == 0, "Failed to initialize WinSock");
|
|
||||||
|
|
||||||
m_signals = new WinAPIEventDriverSignals();
|
auto res = () @trusted { return WSAStartup(0x0202, &wd); } ();
|
||||||
m_timers = new LoopTimeoutTimerDriver();
|
assert(res == 0, "Failed to initialize WinSock");
|
||||||
m_core = new WinAPIEventDriverCore(m_timers);
|
|
||||||
m_events = new WinAPIEventDriverEvents(m_core);
|
m_signals = mallocT!WinAPIEventDriverSignals();
|
||||||
m_files = new WinAPIEventDriverFiles(m_core);
|
m_timers = mallocT!LoopTimeoutTimerDriver();
|
||||||
m_sockets = new WinAPIEventDriverSockets(m_core);
|
m_core = mallocT!WinAPIEventDriverCore(m_timers);
|
||||||
m_dns = new WinAPIEventDriverDNS();
|
m_events = mallocT!WinAPIEventDriverEvents(m_core);
|
||||||
m_watchers = new WinAPIEventDriverWatchers(m_core);
|
m_files = mallocT!WinAPIEventDriverFiles(m_core);
|
||||||
|
m_sockets = mallocT!WinAPIEventDriverSockets(m_core);
|
||||||
|
m_dns = mallocT!WinAPIEventDriverDNS();
|
||||||
|
m_watchers = mallocT!WinAPIEventDriverWatchers(m_core);
|
||||||
}
|
}
|
||||||
|
|
||||||
@safe: /*@nogc:*/ nothrow:
|
@safe: /*@nogc:*/ nothrow:
|
||||||
|
@ -75,8 +78,20 @@ final class WinAPIEventDriver : EventDriver {
|
||||||
{
|
{
|
||||||
if (!m_events) return;
|
if (!m_events) return;
|
||||||
m_events.dispose();
|
m_events.dispose();
|
||||||
m_events = null;
|
m_core.dispose();
|
||||||
assert(threadInstance !is null);
|
assert(threadInstance !is null);
|
||||||
threadInstance = null;
|
threadInstance = null;
|
||||||
|
|
||||||
|
try () @trusted {
|
||||||
|
freeT(m_watchers);
|
||||||
|
freeT(m_dns);
|
||||||
|
freeT(m_sockets);
|
||||||
|
freeT(m_files);
|
||||||
|
freeT(m_events);
|
||||||
|
freeT(m_core);
|
||||||
|
freeT(m_timers);
|
||||||
|
freeT(m_signals);
|
||||||
|
} ();
|
||||||
|
catch (Exception e) assert(false, e.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import eventcore.driver;
|
||||||
import eventcore.drivers.winapi.core;
|
import eventcore.drivers.winapi.core;
|
||||||
import eventcore.internal.win32;
|
import eventcore.internal.win32;
|
||||||
import eventcore.internal.consumablequeue;
|
import eventcore.internal.consumablequeue;
|
||||||
import eventcore.internal.utils : nogc_assert;
|
import eventcore.internal.utils : mallocT, freeT, nogc_assert;
|
||||||
|
|
||||||
|
|
||||||
final class WinAPIEventDriverEvents : EventDriverEvents {
|
final class WinAPIEventDriverEvents : EventDriverEvents {
|
||||||
|
@ -31,10 +31,10 @@ final class WinAPIEventDriverEvents : EventDriverEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
this(WinAPIEventDriverCore core)
|
this(WinAPIEventDriverCore core)
|
||||||
{
|
@nogc {
|
||||||
m_core = core;
|
m_core = core;
|
||||||
m_event = () @trusted { return CreateEvent(null, false, false, null); } ();
|
m_event = () @trusted { return CreateEvent(null, false, false, null); } ();
|
||||||
m_pending = new ConsumableQueue!Trigger; // FIXME: avoid GC allocation
|
m_pending = mallocT!(ConsumableQueue!Trigger); // FIXME: avoid GC allocation
|
||||||
InitializeCriticalSection(&m_mutex);
|
InitializeCriticalSection(&m_mutex);
|
||||||
m_core.registerEvent(m_event, &triggerPending);
|
m_core.registerEvent(m_event, &triggerPending);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ final class WinAPIEventDriverEvents : EventDriverEvents {
|
||||||
void dispose()
|
void dispose()
|
||||||
@trusted {
|
@trusted {
|
||||||
scope (failure) assert(false);
|
scope (failure) assert(false);
|
||||||
destroy(m_pending);
|
freeT(m_pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
override EventID create()
|
override EventID create()
|
||||||
|
|
|
@ -17,7 +17,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
||||||
}
|
}
|
||||||
|
|
||||||
this(WinAPIEventDriverCore core)
|
this(WinAPIEventDriverCore core)
|
||||||
{
|
@nogc {
|
||||||
m_core = core;
|
m_core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
this(WinAPIEventDriverCore core)
|
this(WinAPIEventDriverCore core)
|
||||||
@trusted {
|
@trusted @nogc {
|
||||||
m_tid = GetCurrentThreadId();
|
m_tid = GetCurrentThreadId();
|
||||||
m_core = core;
|
m_core = core;
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
override void cancelRead(StreamSocketFD socket)
|
override void cancelRead(StreamSocketFD socket)
|
||||||
@trusted {
|
@trusted @nogc {
|
||||||
if (!m_sockets[socket].streamSocket.read.callback) return;
|
if (!m_sockets[socket].streamSocket.read.callback) return;
|
||||||
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.read.overlapped);
|
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.read.overlapped);
|
||||||
m_sockets[socket].streamSocket.read.callback = null;
|
m_sockets[socket].streamSocket.read.callback = null;
|
||||||
|
@ -414,7 +414,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
override void cancelWrite(StreamSocketFD socket)
|
override void cancelWrite(StreamSocketFD socket)
|
||||||
@trusted {
|
@trusted @nogc {
|
||||||
if (!m_sockets[socket].streamSocket.write.callback) return;
|
if (!m_sockets[socket].streamSocket.write.callback) return;
|
||||||
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.write.overlapped);
|
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.write.overlapped);
|
||||||
m_sockets[socket].streamSocket.write.callback = null;
|
m_sockets[socket].streamSocket.write.callback = null;
|
||||||
|
@ -549,7 +549,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
override void cancelReceive(DatagramSocketFD socket)
|
override void cancelReceive(DatagramSocketFD socket)
|
||||||
@trusted {
|
@trusted @nogc {
|
||||||
if (!m_sockets[socket].datagramSocket.read.callback) return;
|
if (!m_sockets[socket].datagramSocket.read.callback) return;
|
||||||
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.read.overlapped);
|
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.read.overlapped);
|
||||||
m_sockets[socket].datagramSocket.read.callback = null;
|
m_sockets[socket].datagramSocket.read.callback = null;
|
||||||
|
@ -643,7 +643,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
override void cancelSend(DatagramSocketFD socket)
|
override void cancelSend(DatagramSocketFD socket)
|
||||||
@trusted {
|
@trusted @nogc {
|
||||||
if (!m_sockets[socket].datagramSocket.write.callback) return;
|
if (!m_sockets[socket].datagramSocket.write.callback) return;
|
||||||
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.write.overlapped);
|
CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.write.overlapped);
|
||||||
m_sockets[socket].datagramSocket.write.callback = null;
|
m_sockets[socket].datagramSocket.write.callback = null;
|
||||||
|
@ -719,7 +719,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
override bool releaseRef(SocketFD fd)
|
override bool releaseRef(SocketFD fd)
|
||||||
{
|
@nogc {
|
||||||
import taggedalgebraic : hasType;
|
import taggedalgebraic : hasType;
|
||||||
auto slot = () @trusted { return &m_sockets[fd]; } ();
|
auto slot = () @trusted { return &m_sockets[fd]; } ();
|
||||||
nogc_assert(slot.common.refCount > 0, "Releasing reference to unreferenced socket FD.");
|
nogc_assert(slot.common.refCount > 0, "Releasing reference to unreferenced socket FD.");
|
||||||
|
@ -787,7 +787,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void* rawUserDataImpl(FD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy)
|
private void* rawUserDataImpl(FD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy)
|
||||||
@system {
|
@system @nogc {
|
||||||
SocketSlot* fds = &m_sockets[descriptor].common;
|
SocketSlot* fds = &m_sockets[descriptor].common;
|
||||||
assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy,
|
assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy,
|
||||||
"Requesting user data with differing type (destructor).");
|
"Requesting user data with differing type (destructor).");
|
||||||
|
@ -808,7 +808,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
|
|
||||||
package void clearSocketSlot(FD fd)
|
package void clearSocketSlot(FD fd)
|
||||||
{
|
@nogc {
|
||||||
auto slot = () @trusted { return &m_sockets[fd]; } ();
|
auto slot = () @trusted { return &m_sockets[fd]; } ();
|
||||||
if (slot.common.userDataDestructor)
|
if (slot.common.userDataDestructor)
|
||||||
() @trusted { slot.common.userDataDestructor(slot.common.userData.ptr); } ();
|
() @trusted { slot.common.userDataDestructor(slot.common.userData.ptr); } ();
|
||||||
|
@ -889,8 +889,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWindowClass() nothrow
|
void setupWindowClass()
|
||||||
@trusted {
|
@trusted nothrow @nogc {
|
||||||
static __gshared registered = false;
|
static __gshared registered = false;
|
||||||
|
|
||||||
if (registered) return;
|
if (registered) return;
|
||||||
|
|
|
@ -16,7 +16,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
|
||||||
}
|
}
|
||||||
|
|
||||||
this(WinAPIEventDriverCore core)
|
this(WinAPIEventDriverCore core)
|
||||||
{
|
@nogc {
|
||||||
m_core = core;
|
m_core = core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue