diff --git a/source/eventcore/driver.d b/source/eventcore/driver.d index b783096..76309ff 100644 --- a/source/eventcore/driver.d +++ b/source/eventcore/driver.d @@ -103,8 +103,9 @@ interface EventDriverCore { /// 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. + /** Deprecated - use `EventDriverSockets.userData` instead. */ + deprecated("Use `EventDriverSockets.userData` instead.") @property final ref T userData(T, FD)(FD descriptor) @trusted { import std.conv : emplace; @@ -277,6 +278,21 @@ interface EventDriverSockets { Returns `false` $(I iff) the last reference was removed by this call. */ bool releaseRef(SocketFD descriptor); + + /// 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) + @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); + } } diff --git a/source/eventcore/drivers/posix/sockets.d b/source/eventcore/drivers/posix/sockets.d index 9c7b6ce..f281182 100644 --- a/source/eventcore/drivers/posix/sockets.d +++ b/source/eventcore/drivers/posix/sockets.d @@ -728,6 +728,30 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets return true; } + final protected override void* rawUserData(StreamSocketFD 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); + } + + 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; + } + private sock_t createSocket(AddressFamily family, int type) { sock_t sock; diff --git a/source/eventcore/drivers/winapi/sockets.d b/source/eventcore/drivers/winapi/sockets.d index 090fac7..ca83e87 100644 --- a/source/eventcore/drivers/winapi/sockets.d +++ b/source/eventcore/drivers/winapi/sockets.d @@ -134,4 +134,14 @@ final class WinAPIEventDriverSockets : EventDriverSockets { { assert(false, "TODO!"); } + + protected override void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system + { + assert(false, "TODO!"); + } + + protected override void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system + { + assert(false, "TODO!"); + } }