From 7bfbb64899e89a0ced4236aacd16b1c603cca82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Fri, 16 Mar 2018 12:22:50 +0100 Subject: [PATCH] Add userData!T properties for all descriptor based primitives. --- source/eventcore/driver.d | 65 ++++++++++++++++++++-- source/eventcore/drivers/posix/driver.d | 27 +++++---- source/eventcore/drivers/posix/events.d | 5 ++ source/eventcore/drivers/posix/sockets.d | 28 ++++------ source/eventcore/drivers/posix/watchers.d | 16 ++++++ source/eventcore/drivers/threadedfile.d | 19 ++++++- source/eventcore/drivers/timer.d | 17 ++++++ source/eventcore/drivers/winapi/core.d | 17 ++++++ source/eventcore/drivers/winapi/events.d | 5 ++ source/eventcore/drivers/winapi/files.d | 5 ++ source/eventcore/drivers/winapi/sockets.d | 7 ++- source/eventcore/drivers/winapi/watchers.d | 5 ++ 12 files changed, 180 insertions(+), 36 deletions(-) diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index 613a90b..8d83f35 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -327,11 +327,6 @@ interface EventDriverSockets { /// ditto bool setOption(StreamSocketFD socket, StreamSocketOption option, bool enable); - /// Low-level user data access. Use `getUserData` instead. - protected void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; - /// ditto - protected void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; - /** Retrieves a reference to a user-defined value associated with a descriptor. */ @property final ref T userData(T, FD)(FD descriptor) @@ -341,6 +336,13 @@ interface EventDriverSockets { static void destr(void* ptr) { destroy(*cast(T*)ptr); } return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); } + + /// Low-level user data access. Use `getUserData` instead. + protected void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; + /// ditto + protected void* rawUserData(StreamListenSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; + /// ditto + protected void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; } @@ -384,8 +386,22 @@ interface EventDriverFiles { Returns `false` $(I iff) the last reference was removed by this call. */ bool releaseRef(FileFD descriptor); + + /** Retrieves a reference to a user-defined value associated with a descriptor. + */ + @property final ref T userData(T)(FileFD descriptor) + @trusted { + import std.conv : emplace; + static void init(void* ptr) { emplace(cast(T*)ptr); } + static void destr(void* ptr) { destroy(*cast(T*)ptr); } + return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); + } + + /// Low-level user data access. Use `userData` instead. + protected void* rawUserData(FileFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; } + /** Cross-thread notifications "Events" can be used to wake up the event loop of a foreign thread. This is @@ -428,6 +444,19 @@ interface EventDriverEvents { Returns `false` $(I iff) the last reference was removed by this call. */ bool releaseRef(EventID descriptor); + + /** Retrieves a reference to a user-defined value associated with a descriptor. + */ + @property final ref T userData(T)(EventID descriptor) + @trusted { + import std.conv : emplace; + static void init(void* ptr) { emplace(cast(T*)ptr); } + static void destr(void* ptr) { destroy(*cast(T*)ptr); } + return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); + } + + /// Low-level user data access. Use `userData` instead. + protected void* rawUserData(EventID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; } @@ -496,6 +525,19 @@ interface EventDriverTimers { /// Determines if the given timer's reference count equals one. bool isUnique(TimerID descriptor) const; + + /** Retrieves a reference to a user-defined value associated with a descriptor. + */ + @property final ref T userData(T)(TimerID descriptor) + @trusted { + import std.conv : emplace; + static void init(void* ptr) { emplace(cast(T*)ptr); } + static void destr(void* ptr) { destroy(*cast(T*)ptr); } + return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); + } + + /// Low-level user data access. Use `userData` instead. + protected void* rawUserData(TimerID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; } interface EventDriverWatchers { @@ -516,6 +558,19 @@ interface EventDriverWatchers { Returns `false` $(I iff) the last reference was removed by this call. */ bool releaseRef(WatcherID descriptor); + + /** Retrieves a reference to a user-defined value associated with a descriptor. + */ + @property final ref T userData(T)(WatcherID descriptor) + @trusted { + import std.conv : emplace; + static void init(void* ptr) { emplace(cast(T*)ptr); } + static void destr(void* ptr) { destroy(*cast(T*)ptr); } + return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); + } + + /// Low-level user data access. Use `userData` instead. + protected void* rawUserData(WatcherID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; } diff --git a/source/eventcore/drivers/posix/driver.d b/source/eventcore/drivers/posix/driver.d index 629db99..5f84e8a 100644 --- a/source/eventcore/drivers/posix/driver.d +++ b/source/eventcore/drivers/posix/driver.d @@ -192,18 +192,9 @@ final class PosixEventDriverCore(Loop : PosixEventLoop, Timers : EventDriverTime return rawUserDataImpl(descriptor, size, initialize, destroy); } - private void* rawUserDataImpl(FD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + protected final void* rawUserDataImpl(FD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system { - FDSlot* fds = &m_loop.m_fds[descriptor].common; - assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, - "Requesting user data with differing type (destructor)."); - assert(size <= FDSlot.userData.length, "Requested user data is too large."); - if (size > FDSlot.userData.length) assert(false); - if (!fds.userDataDestructor) { - initialize(fds.userData.ptr); - fds.userDataDestructor = destroy; - } - return m_loop.m_fds[descriptor].common.userData.ptr; + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); } } @@ -281,6 +272,20 @@ package class PosixEventLoop { m_waiterCount--; *slot = m_fds.FullField.init; } + + package final void* rawUserDataImpl(size_t descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + FDSlot* fds = &m_fds[descriptor].common; + assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, + "Requesting user data with differing type (destructor)."); + assert(size <= FDSlot.userData.length, "Requested user data is too large."); + if (size > FDSlot.userData.length) assert(false); + if (!fds.userDataDestructor) { + initialize(fds.userData.ptr); + fds.userDataDestructor = destroy; + } + return fds.userData.ptr; + } } diff --git a/source/eventcore/drivers/posix/events.d b/source/eventcore/drivers/posix/events.d index 0cb5b0d..5c57cd7 100644 --- a/source/eventcore/drivers/posix/events.d +++ b/source/eventcore/drivers/posix/events.d @@ -227,6 +227,11 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS return true; } + final protected override void* rawUserData(EventID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); + } + private EventSlot* getSlot(EventID id) { nogc_assert(id < m_loop.m_fds.length, "Invalid event ID."); diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index 610aeef..2f96277 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -799,8 +799,9 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets final override void addRef(SocketFD fd) { - assert(m_loop.m_fds[fd].common.refCount > 0, "Adding reference to unreferenced socket FD."); - m_loop.m_fds[fd].common.refCount++; + auto slot = () @trusted { return &m_loop.m_fds[fd]; } (); + assert(slot.common.refCount > 0, "Adding reference to unreferenced socket FD."); + slot.common.refCount++; } final override bool releaseRef(SocketFD fd) @@ -843,26 +844,17 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets final protected override void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system { - return rawUserDataImpl(descriptor, size, initialize, destroy); + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); + } + + final protected override void* rawUserData(StreamListenSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); } final protected override void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system { - return rawUserDataImpl(descriptor, size, initialize, destroy); - } - - private void* rawUserDataImpl(FD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) - @system { - auto fds = &m_loop.m_fds[descriptor].common; - assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, - "Requesting user data with differing type (destructor)."); - assert(size <= fds.userData.length, "Requested user data is too large."); - if (size > fds.userData.length) assert(false); - if (!fds.userDataDestructor) { - initialize(fds.userData.ptr); - fds.userDataDestructor = destroy; - } - return m_loop.m_fds[descriptor].common.userData.ptr; + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); } private sock_t createSocket(AddressFamily family, int type) diff --git a/source/eventcore/drivers/posix/watchers.d b/source/eventcore/drivers/posix/watchers.d index 288af0f..9878041 100644 --- a/source/eventcore/drivers/posix/watchers.d +++ b/source/eventcore/drivers/posix/watchers.d @@ -77,6 +77,11 @@ final class InotifyEventDriverWatchers(Events : EventDriverEvents) : EventDriver return true; } + final protected override void* rawUserData(WatcherID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); + } + private void onChanges(FD fd) { processEvents(cast(WatcherID)fd); @@ -211,6 +216,12 @@ final class FSEventsEventDriverWatchers(Events : EventDriverEvents) : EventDrive FSEventStreamRelease*/ assert(false, "TODO!"); } + + final protected override void* rawUserData(WatcherID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_loop.rawUserDataImpl(descriptor, size, initialize, destroy); + } + } @@ -294,6 +305,11 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat return true; } + final protected override void* rawUserData(WatcherID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_events.loop.rawUserDataImpl(cast(EventID)descriptor, size, initialize, destroy); + } + private void onEvent(EventID evt) { import std.algorithm.mutation : swap; diff --git a/source/eventcore/drivers/threadedfile.d b/source/eventcore/drivers/threadedfile.d index 9bb76fb..7f0a3f1 100644 --- a/source/eventcore/drivers/threadedfile.d +++ b/source/eventcore/drivers/threadedfile.d @@ -101,11 +101,14 @@ final class ThreadedFileEventDriver(Events : EventDriverEvents) : EventDriverFil static struct FileInfo { IOInfo read; IOInfo write; + int refCount; + DataInitializer userDataDestructor; + ubyte[16*size_t.sizeof] userData; } TaskPool m_fileThreadPool; - ChoppedVector!FileInfo m_files; + ChoppedVector!FileInfo m_files; // TODO: use the one from the posix loop SmallIntegerSet!FileFD m_activeReads; SmallIntegerSet!FileFD m_activeWrites; EventID m_readyEvent = EventID.invalid; @@ -268,6 +271,20 @@ final class ThreadedFileEventDriver(Events : EventDriverEvents) : EventDriverFil return true; } + protected final override void* rawUserData(FileFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + FileInfo* fds = &m_files[descriptor]; + assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, + "Requesting user data with differing type (destructor)."); + assert(size <= FileInfo.userData.length, "Requested user data is too large."); + if (size > FileInfo.userData.length) assert(false); + if (!fds.userDataDestructor) { + initialize(fds.userData.ptr); + fds.userDataDestructor = destroy; + } + return fds.userData.ptr; + } + /// private static void taskFun(string op, UB)(ThreadedFileEventDriver fd, FileFD file, ulong offset, UB[] buffer) { diff --git a/source/eventcore/drivers/timer.d b/source/eventcore/drivers/timer.d index 2e1a420..926400b 100644 --- a/source/eventcore/drivers/timer.d +++ b/source/eventcore/drivers/timer.d @@ -170,6 +170,20 @@ final class LoopTimeoutTimerDriver : EventDriverTimers { return m_timers[descriptor].refCount == 1; } + protected final override void* rawUserData(TimerID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + TimerSlot* fds = m_timers[descriptor]; + assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, + "Requesting user data with differing type (destructor)."); + assert(size <= TimerSlot.userData.length, "Requested user data is too large."); + if (size > TimerSlot.userData.length) assert(false); + if (!fds.userDataDestructor) { + initialize(fds.userData.ptr); + fds.userDataDestructor = destroy; + } + return fds.userData.ptr; + } + private void enqueueTimer(TimerSlot* tm) nothrow { TimerSlot* ns; @@ -192,4 +206,7 @@ struct TimerSlot { long timeout; // stdtime long repeatDuration; TimerCallback callback; // TODO: use a list with small-value optimization + + DataInitializer userDataDestructor; + ubyte[16*size_t.sizeof] userData; } diff --git a/source/eventcore/drivers/winapi/core.d b/source/eventcore/drivers/winapi/core.d index d426fce..dea8a88 100644 --- a/source/eventcore/drivers/winapi/core.d +++ b/source/eventcore/drivers/winapi/core.d @@ -98,6 +98,20 @@ final class WinAPIEventDriverCore : EventDriverCore { m_exit = false; } + package void* rawUserDataImpl(HANDLE handle, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + HandleSlot* fds = &m_handles[handle]; + assert(fds.userDataDestructor is null || fds.userDataDestructor is destroy, + "Requesting user data with differing type (destructor)."); + assert(size <= HandleSlot.userData.length, "Requested user data is too large."); + if (size > HandleSlot.userData.length) assert(false); + if (!fds.userDataDestructor) { + initialize(fds.userData.ptr); + fds.userDataDestructor = destroy; + } + return fds.userData.ptr; + } + protected override void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system { assert(false, "TODO!"); @@ -208,6 +222,9 @@ private struct HandleSlot { int refCount; TaggedAlgebraic!SpecificTypes specific; + DataInitializer userDataDestructor; + ubyte[16*size_t.sizeof] userData; + @safe nothrow: @property ref FileSlot file() { return specific.get!FileSlot; } diff --git a/source/eventcore/drivers/winapi/events.d b/source/eventcore/drivers/winapi/events.d index e71c6cb..c76b224 100644 --- a/source/eventcore/drivers/winapi/events.d +++ b/source/eventcore/drivers/winapi/events.d @@ -126,6 +126,11 @@ final class WinAPIEventDriverEvents : EventDriverEvents { return true; } + protected override void* rawUserData(EventID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_core.rawUserDataImpl(idToHandle(descriptor), size, initialize, destroy); + } + private void triggerPending() { while (true) { diff --git a/source/eventcore/drivers/winapi/files.d b/source/eventcore/drivers/winapi/files.d index 3297989..035a5f6 100644 --- a/source/eventcore/drivers/winapi/files.d +++ b/source/eventcore/drivers/winapi/files.d @@ -154,6 +154,11 @@ final class WinAPIEventDriverFiles : EventDriverFiles { }); } + protected override void* rawUserData(FileFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_core.rawUserDataImpl(idToHandle(descriptor), size, initialize, destroy); + } + private static void startIO(alias fun, bool RO)(HANDLE h, FileSlot.Direction!RO* slot) { import std.algorithm.comparison : min; diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index da97b93..7200dd9 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -754,6 +754,11 @@ final class WinAPIEventDriverSockets : EventDriverSockets { return rawUserDataImpl(descriptor, size, initialize, destroy); } + final protected override void* rawUserData(StreamListenSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return rawUserDataImpl(descriptor, size, initialize, destroy); + } + final protected override void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system { return rawUserDataImpl(descriptor, size, initialize, destroy); @@ -770,7 +775,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets { initialize(fds.userData.ptr); fds.userDataDestructor = destroy; } - return m_sockets[descriptor].common.userData.ptr; + return fds.userData.ptr; } private void initSocketSlot(SocketFD fd) diff --git a/source/eventcore/drivers/winapi/watchers.d b/source/eventcore/drivers/winapi/watchers.d index 702ba0c..2ec45eb 100644 --- a/source/eventcore/drivers/winapi/watchers.d +++ b/source/eventcore/drivers/winapi/watchers.d @@ -69,6 +69,11 @@ final class WinAPIEventDriverWatchers : EventDriverWatchers { return doReleaseRef(idToHandle(descriptor)); } + protected override void* rawUserData(WatcherID descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) + @system { + return m_core.rawUserDataImpl(idToHandle(descriptor), size, initialize, destroy); + } + private static bool doReleaseRef(HANDLE handle) { auto core = WinAPIEventDriver.threadInstance.core;