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.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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -17,7 +17,7 @@ final class WinAPIEventDriverFiles : EventDriverFiles {
|
|||
}
|
||||
|
||||
this(WinAPIEventDriverCore core)
|
||||
{
|
||||
@nogc {
|
||||
m_core = core;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -16,7 +16,7 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers {
|
|||
}
|
||||
|
||||
this(WinAPIEventDriverCore core)
|
||||
{
|
||||
@nogc {
|
||||
m_core = core;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue