From 284d4f43c3a5dc0ade56547ae41af08ce9682756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Mon, 22 Oct 2018 22:05:37 +0200 Subject: [PATCH] Make the WinAPI driver initialization nogc. --- source/eventcore/drivers/winapi/core.d | 48 ++++++++++++++-------- source/eventcore/drivers/winapi/driver.d | 37 ++++++++++++----- source/eventcore/drivers/winapi/events.d | 8 ++-- source/eventcore/drivers/winapi/files.d | 2 +- source/eventcore/drivers/winapi/sockets.d | 20 ++++----- source/eventcore/drivers/winapi/watchers.d | 2 +- 6 files changed, 72 insertions(+), 45 deletions(-) diff --git a/source/eventcore/drivers/winapi/core.d b/source/eventcore/drivers/winapi/core.d index e10c8ad..1c55fa8 100644 --- a/source/eventcore/drivers/winapi/core.d +++ b/source/eventcore/drivers/winapi/core.d @@ -5,7 +5,7 @@ version (Windows): import eventcore.driver; import eventcore.drivers.timer; import eventcore.internal.consumablequeue; -import eventcore.internal.utils : nogc_assert; +import eventcore.internal.utils : mallocT, freeT, nogc_assert; import eventcore.internal.win32; import core.sync.mutex : Mutex; import core.time : Duration; @@ -21,8 +21,9 @@ final class WinAPIEventDriverCore : EventDriverCore { size_t m_waiterCount; DWORD m_tid; LoopTimeoutTimerDriver m_timers; - HANDLE[] m_registeredEvents; - void delegate() @safe nothrow[HANDLE] m_eventCallbacks; + HANDLE[MAXIMUM_WAIT_OBJECTS] m_registeredEvents; + void delegate() @safe nothrow[MAXIMUM_WAIT_OBJECTS] m_registeredEventCallbacks; + DWORD m_registeredEventCount = 0; HANDLE m_fileCompletionEvent; ConsumableQueue!IOEvent m_ioEvents; @@ -35,27 +36,36 @@ final class WinAPIEventDriverCore : EventDriverCore { } this(LoopTimeoutTimerDriver timers) - { + @nogc { m_timers = timers; m_tid = () @trusted { return GetCurrentThreadId(); } (); m_fileCompletionEvent = () @trusted { return CreateEventW(null, false, false, null); } (); registerEvent(m_fileCompletionEvent); - m_ioEvents = new ConsumableQueue!IOEvent; + m_ioEvents = mallocT!(ConsumableQueue!IOEvent); static if (__VERSION__ >= 2074) - m_threadCallbackMutex = new shared Mutex; + m_threadCallbackMutex = mallocT!(shared(Mutex)); 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); } + 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; } - package void addWaiter() { m_waiterCount++; } + package void addWaiter() @nogc { m_waiterCount++; } package void removeWaiter() - { + @nogc { assert(m_waiterCount > 0, "Decrementing waiter count below zero."); m_waiterCount--; } @@ -159,7 +169,7 @@ final class WinAPIEventDriverCore : EventDriverCore { bool got_event; 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); } (); while (!m_ioEvents.empty) { @@ -168,9 +178,9 @@ final class WinAPIEventDriverCore : EventDriverCore { } 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) { - (*pc)(); + else if (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + m_registeredEventCount) { + if (auto cb = m_registeredEventCallbacks[ret - WAIT_OBJECT_0]) { + cb(); got_event = true; } } @@ -209,9 +219,11 @@ final class WinAPIEventDriverCore : EventDriverCore { package void registerEvent(HANDLE event, void delegate() @safe nothrow callback = null) - { - m_registeredEvents ~= event; - if (callback) m_eventCallbacks[event] = callback; + @nogc { + assert(m_registeredEventCount < MAXIMUM_WAIT_OBJECTS, "Too many registered events."); + m_registeredEvents[m_registeredEventCount] = event; + if (callback) m_registeredEventCallbacks[m_registeredEventCount] = callback; + m_registeredEventCount++; } package SlotType* setupSlot(SlotType)(HANDLE h) @@ -231,7 +243,7 @@ final class WinAPIEventDriverCore : EventDriverCore { } package void discardEvents(scope OVERLAPPED_CORE*[] overlapped...) - { +@nogc { import std.algorithm.searching : canFind; m_ioEvents.filterPending!(evt => !overlapped.canFind(evt.overlapped)); } diff --git a/source/eventcore/drivers/winapi/driver.d b/source/eventcore/drivers/winapi/driver.d index 7ef3281..d8bd0c3 100644 --- a/source/eventcore/drivers/winapi/driver.d +++ b/source/eventcore/drivers/winapi/driver.d @@ -18,6 +18,7 @@ import eventcore.drivers.winapi.files; import eventcore.drivers.winapi.signals; import eventcore.drivers.winapi.sockets; import eventcore.drivers.winapi.watchers; +import eventcore.internal.utils : mallocT, freeT; import core.sys.windows.windows; static assert(HANDLE.sizeof <= FD.BaseType.sizeof); @@ -39,23 +40,25 @@ final class WinAPIEventDriver : EventDriver { static WinAPIEventDriver threadInstance; this() - @safe { + @safe nothrow @nogc { assert(threadInstance is null); threadInstance = this; import std.exception : enforce; WSADATA wd; - enforce(() @trusted { return WSAStartup(0x0202, &wd); } () == 0, "Failed to initialize WinSock"); - m_signals = new WinAPIEventDriverSignals(); - m_timers = new LoopTimeoutTimerDriver(); - m_core = new WinAPIEventDriverCore(m_timers); - m_events = new WinAPIEventDriverEvents(m_core); - m_files = new WinAPIEventDriverFiles(m_core); - m_sockets = new WinAPIEventDriverSockets(m_core); - m_dns = new WinAPIEventDriverDNS(); - m_watchers = new WinAPIEventDriverWatchers(m_core); + auto res = () @trusted { return WSAStartup(0x0202, &wd); } (); + assert(res == 0, "Failed to initialize WinSock"); + + m_signals = mallocT!WinAPIEventDriverSignals(); + m_timers = mallocT!LoopTimeoutTimerDriver(); + m_core = mallocT!WinAPIEventDriverCore(m_timers); + m_events = mallocT!WinAPIEventDriverEvents(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: @@ -75,8 +78,20 @@ final class WinAPIEventDriver : EventDriver { { if (!m_events) return; m_events.dispose(); - m_events = null; + m_core.dispose(); assert(threadInstance !is 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); } } diff --git a/source/eventcore/drivers/winapi/events.d b/source/eventcore/drivers/winapi/events.d index c76b224..0134c0c 100644 --- a/source/eventcore/drivers/winapi/events.d +++ b/source/eventcore/drivers/winapi/events.d @@ -6,7 +6,7 @@ import eventcore.driver; import eventcore.drivers.winapi.core; import eventcore.internal.win32; import eventcore.internal.consumablequeue; -import eventcore.internal.utils : nogc_assert; +import eventcore.internal.utils : mallocT, freeT, nogc_assert; final class WinAPIEventDriverEvents : EventDriverEvents { @@ -31,10 +31,10 @@ final class WinAPIEventDriverEvents : EventDriverEvents { } this(WinAPIEventDriverCore core) - { + @nogc { m_core = core; 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); m_core.registerEvent(m_event, &triggerPending); } @@ -42,7 +42,7 @@ final class WinAPIEventDriverEvents : EventDriverEvents { void dispose() @trusted { scope (failure) assert(false); - destroy(m_pending); + freeT(m_pending); } override EventID create() diff --git a/source/eventcore/drivers/winapi/files.d b/source/eventcore/drivers/winapi/files.d index 5dac5f8..32bae89 100644 --- a/source/eventcore/drivers/winapi/files.d +++ b/source/eventcore/drivers/winapi/files.d @@ -17,7 +17,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles { } this(WinAPIEventDriverCore core) - { + @nogc { m_core = core; } diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index 7ef71fb..1263926 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -25,7 +25,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } this(WinAPIEventDriverCore core) - @trusted { + @trusted @nogc { m_tid = GetCurrentThreadId(); m_core = core; @@ -406,7 +406,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } override void cancelRead(StreamSocketFD socket) - @trusted { + @trusted @nogc { if (!m_sockets[socket].streamSocket.read.callback) return; CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.read.overlapped); m_sockets[socket].streamSocket.read.callback = null; @@ -414,7 +414,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } override void cancelWrite(StreamSocketFD socket) - @trusted { + @trusted @nogc { if (!m_sockets[socket].streamSocket.write.callback) return; CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].streamSocket.write.overlapped); m_sockets[socket].streamSocket.write.callback = null; @@ -549,7 +549,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } override void cancelReceive(DatagramSocketFD socket) - @trusted { + @trusted @nogc { if (!m_sockets[socket].datagramSocket.read.callback) return; CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.read.overlapped); m_sockets[socket].datagramSocket.read.callback = null; @@ -643,7 +643,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } override void cancelSend(DatagramSocketFD socket) - @trusted { + @trusted @nogc { if (!m_sockets[socket].datagramSocket.write.callback) return; CancelIoEx(cast(HANDLE)cast(SOCKET)socket, cast(LPOVERLAPPED)&m_sockets[socket].datagramSocket.write.overlapped); m_sockets[socket].datagramSocket.write.callback = null; @@ -719,7 +719,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } override bool releaseRef(SocketFD fd) - { + @nogc { import taggedalgebraic : hasType; auto slot = () @trusted { return &m_sockets[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) - @system { + @system @nogc { SocketSlot* fds = &m_sockets[descriptor].common; assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, "Requesting user data with differing type (destructor)."); @@ -808,7 +808,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } package void clearSocketSlot(FD fd) - { + @nogc { auto slot = () @trusted { return &m_sockets[fd]; } (); if (slot.common.userDataDestructor) () @trusted { slot.common.userDataDestructor(slot.common.userData.ptr); } (); @@ -889,8 +889,8 @@ final class WinAPIEventDriverSockets : EventDriverSockets { } } -void setupWindowClass() nothrow -@trusted { +void setupWindowClass() +@trusted nothrow @nogc { static __gshared registered = false; if (registered) return; diff --git a/source/eventcore/drivers/winapi/watchers.d b/source/eventcore/drivers/winapi/watchers.d index ea6bdb6..bb7c162 100644 --- a/source/eventcore/drivers/winapi/watchers.d +++ b/source/eventcore/drivers/winapi/watchers.d @@ -16,7 +16,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { } this(WinAPIEventDriverCore core) - { + @nogc { m_core = core; }