Make the Posix driver initialization nogc.

This commit is contained in:
Sönke Ludwig 2018-10-21 20:16:26 +02:00
parent a4eaafce9a
commit e7e4a0f5f5
9 changed files with 128 additions and 85 deletions

View file

@ -352,13 +352,31 @@ interface EventDriverSockets {
/** Retrieves a reference to a user-defined value associated with a descriptor. /** Retrieves a reference to a user-defined value associated with a descriptor.
*/ */
@property final ref T userData(T, FD)(FD descriptor) @property final ref T userData(T, FD)(FD descriptor) @trusted
@trusted { if (!hasNoGCLifetime!T)
{
import std.conv : emplace; import std.conv : emplace;
static void init(void* ptr) { emplace(cast(T*)ptr); } static void init(void* ptr) { emplace(cast(T*)ptr); }
static void destr(void* ptr) { destroy(*cast(T*)ptr); } static void destr(void* ptr) { destroy(*cast(T*)ptr); }
return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr); return *cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr);
} }
/// ditto
@property final ref T userData(T, FD)(FD descriptor) @trusted @nogc
if (hasNoGCLifetime!T)
{
import std.conv : emplace;
static void init(void* ptr) @nogc { emplace(cast(T*)ptr); }
static void destr(void* ptr) @nogc { destroy(*cast(T*)ptr); }
scope getter = {
return cast(T*)rawUserData(descriptor, T.sizeof, &init, &destr);
};
static if (__traits(compiles, () nothrow @trusted { getter(); }))
return *(cast(T* delegate() @nogc nothrow)getter)();
else
return *(cast(T* delegate() @nogc)getter)();
}
/// Low-level user data access. Use `getUserData` instead. /// Low-level user data access. Use `getUserData` instead.
protected void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; protected void* rawUserData(StreamSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system;
@ -368,6 +386,14 @@ interface EventDriverSockets {
protected void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system; protected void* rawUserData(DatagramSocketFD descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) @system;
} }
enum hasNoGCLifetime(T) = __traits(compiles, () @nogc @trusted { import std.conv : emplace; T b = void; emplace!T(&b); destroy(b); });
unittest {
static struct S1 {}
static struct S2 { ~this() { new int; } }
static assert(hasNoGCLifetime!S1);
static assert(!hasNoGCLifetime!S2);
}
/** Performs asynchronous DNS queries. /** Performs asynchronous DNS queries.
*/ */

View file

@ -43,7 +43,7 @@ final class EventDriverDNS_GAI(Events : EventDriverEvents, Signals : EventDriver
} }
this(Events events, Signals signals) this(Events events, Signals signals)
{ @nogc {
m_events = events; m_events = events;
setupEvent(); setupEvent();
} }
@ -139,7 +139,7 @@ final class EventDriverDNS_GAI(Events : EventDriverEvents, Signals : EventDriver
} }
private void setupEvent() private void setupEvent()
{ @nogc {
if (m_event == EventID.invalid) { if (m_event == EventID.invalid) {
m_event = m_events.createInternal(); m_event = m_events.createInternal();
m_events.wait(m_event, &onDNSSignal); m_events.wait(m_event, &onDNSSignal);

View file

@ -64,16 +64,16 @@ final class PosixEventDriver(Loop : PosixEventLoop) : EventDriver {
} }
this() this()
{ @nogc @trusted {
m_loop = new Loop; m_loop = mallocT!Loop;
m_sockets = new SocketsDriver(m_loop); m_sockets = mallocT!SocketsDriver(m_loop);
m_events = new EventsDriver(m_loop, m_sockets); m_events = mallocT!EventsDriver(m_loop, m_sockets);
m_signals = new SignalsDriver(m_loop); m_signals = mallocT!SignalsDriver(m_loop);
m_timers = new TimerDriver; m_timers = mallocT!TimerDriver;
m_core = new CoreDriver(m_loop, m_timers, m_events); m_core = mallocT!CoreDriver(m_loop, m_timers, m_events);
m_dns = new DNSDriver(m_events, m_signals); m_dns = mallocT!DNSDriver(m_events, m_signals);
m_files = new FileDriver(m_events); m_files = mallocT!FileDriver(m_events);
m_watchers = new WatcherDriver(m_events); m_watchers = mallocT!WatcherDriver(m_events);
} }
// force overriding these in the (final) sub classes to avoid virtual calls // force overriding these in the (final) sub classes to avoid virtual calls
@ -96,6 +96,19 @@ final class PosixEventDriver(Loop : PosixEventLoop) : EventDriver {
m_core.dispose(); m_core.dispose();
m_loop.dispose(); m_loop.dispose();
m_loop = null; m_loop = null;
try () @trusted {
freeT(m_watchers);
freeT(m_files);
freeT(m_dns);
freeT(m_core);
freeT(m_timers);
freeT(m_signals);
freeT(m_events);
freeT(m_sockets);
freeT(m_loop);
} ();
catch (Exception e) assert(false, e.msg);
} }
} }
@ -121,29 +134,32 @@ final class PosixEventDriverCore(Loop : PosixEventLoop, Timers : EventDriverTime
ConsumableQueue!(Tuple!(ThreadCallback, intptr_t)) m_threadCallbacks; ConsumableQueue!(Tuple!(ThreadCallback, intptr_t)) m_threadCallbacks;
} }
protected this(Loop loop, Timers timers, Events events) this(Loop loop, Timers timers, Events events)
{ @nogc {
m_loop = loop; m_loop = loop;
m_timers = timers; m_timers = timers;
m_events = events; m_events = events;
m_wakeupEvent = events.createInternal(); m_wakeupEvent = events.createInternal();
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);
} }
protected final void dispose() final void dispose()
{ {
executeThreadCallbacks(); executeThreadCallbacks();
m_events.releaseRef(m_wakeupEvent); m_events.releaseRef(m_wakeupEvent);
atomicStore(m_threadCallbackMutex, null);
m_wakeupEvent = EventID.invalid; // FIXME: this needs to be synchronized! m_wakeupEvent = EventID.invalid; // FIXME: this needs to be synchronized!
try {
() @trusted { freeT(m_threadCallbackMutex); } ();
() @trusted { freeT(m_threadCallbacks); } ();
} catch (Exception e) assert(false, e.msg);
} }
@property size_t waiterCount() const { return m_loop.m_waiterCount + m_timers.pendingCount; } @property size_t waiterCount() const { return m_loop.m_waiterCount + m_timers.pendingCount; }
@ -274,11 +290,11 @@ package class PosixEventLoop {
protected abstract bool doProcessEvents(Duration dur); protected abstract bool doProcessEvents(Duration dur);
/// Registers the FD for general notification reception. /// Registers the FD for general notification reception.
protected abstract void registerFD(FD fd, EventMask mask, bool edge_triggered = true); protected abstract void registerFD(FD fd, EventMask mask, bool edge_triggered = true) @nogc;
/// Unregisters the FD for general notification reception. /// Unregisters the FD for general notification reception.
protected abstract void unregisterFD(FD fd, EventMask mask); protected abstract void unregisterFD(FD fd, EventMask mask) @nogc;
/// Updates the event mask to use for listening for notifications. /// Updates the event mask to use for listening for notifications.
protected abstract void updateFD(FD fd, EventMask old_mask, EventMask new_mask, bool edge_triggered = true); protected abstract void updateFD(FD fd, EventMask old_mask, EventMask new_mask, bool edge_triggered = true) @nogc;
final protected void notify(EventType evt)(FD fd) final protected void notify(EventType evt)(FD fd)
{ {
@ -342,7 +358,7 @@ package class PosixEventLoop {
} }
package final void* rawUserDataImpl(size_t descriptor, size_t size, DataInitializer initialize, DataInitializer destroy) package final void* rawUserDataImpl(size_t descriptor, size_t size, DataInitializer initialize, DataInitializer destroy)
@system { @system @nogc {
FDSlot* fds = &m_fds[descriptor].common; FDSlot* fds = &m_fds[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).");

View file

@ -5,7 +5,7 @@
numbers of concurrently open sockets. numbers of concurrently open sockets.
*/ */
module eventcore.drivers.posix.epoll; module eventcore.drivers.posix.epoll;
@safe: /*@nogc:*/ nothrow: @safe @nogc nothrow:
version (linux): version (linux):
@ -22,17 +22,16 @@ static if (!is(typeof(SOCK_CLOEXEC)))
enum SOCK_CLOEXEC = 0x80000; enum SOCK_CLOEXEC = 0x80000;
final class EpollEventLoop : PosixEventLoop { final class EpollEventLoop : PosixEventLoop {
@safe: nothrow: @safe nothrow:
private { private {
int m_epoll; int m_epoll;
epoll_event[] m_events; epoll_event[100] m_events;
} }
this() this()
{ @nogc {
m_epoll = () @trusted { return epoll_create1(SOCK_CLOEXEC); } (); m_epoll = () @trusted { return epoll_create1(SOCK_CLOEXEC); } ();
m_events.length = 100;
} }
override bool doProcessEvents(Duration timeout) override bool doProcessEvents(Duration timeout)
@ -60,7 +59,7 @@ final class EpollEventLoop : PosixEventLoop {
} }
override void dispose() override void dispose()
{ @nogc {
import core.sys.posix.unistd : close; import core.sys.posix.unistd : close;
close(m_epoll); close(m_epoll);
} }

View file

@ -4,7 +4,8 @@ module eventcore.drivers.posix.events;
import eventcore.driver; import eventcore.driver;
import eventcore.drivers.posix.driver; import eventcore.drivers.posix.driver;
import eventcore.internal.consumablequeue : ConsumableQueue; import eventcore.internal.consumablequeue : ConsumableQueue;
import eventcore.internal.utils : nogc_assert; import eventcore.internal.utils : nogc_assert, mallocT, freeT;
version (linux) { version (linux) {
nothrow @nogc extern (C) int eventfd(uint initval, int flags); nothrow @nogc extern (C) int eventfd(uint initval, int flags);
@ -25,21 +26,12 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
Loop m_loop; Loop m_loop;
Sockets m_sockets; Sockets m_sockets;
ubyte[ulong.sizeof] m_buf; ubyte[ulong.sizeof] m_buf;
version (linux) {}
else {
// TODO: avoid the overhead of a mutex backed map here
import core.sync.mutex : Mutex;
Mutex m_eventsMutex;
EventID[DatagramSocketFD] m_events;
}
} }
this(Loop loop, Sockets sockets) this(Loop loop, Sockets sockets)
{ @nogc {
m_loop = loop; m_loop = loop;
m_sockets = sockets; m_sockets = sockets;
version (linux) {}
else m_eventsMutex = new Mutex;
} }
package @property Loop loop() { return m_loop; } package @property Loop loop() { return m_loop; }
@ -50,14 +42,14 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
package(eventcore) EventID createInternal(bool is_internal = true) package(eventcore) EventID createInternal(bool is_internal = true)
{ @nogc {
version (linux) { version (linux) {
auto eid = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); auto eid = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (eid == -1) return EventID.invalid; if (eid == -1) return EventID.invalid;
auto id = cast(EventID)eid; auto id = cast(EventID)eid;
// FIXME: avoid dynamic memory allocation for the queue // FIXME: avoid dynamic memory allocation for the queue
m_loop.initFD(id, FDFlags.internal, m_loop.initFD(id, FDFlags.internal,
EventSlot(new ConsumableQueue!EventCallback, false, is_internal)); EventSlot(mallocT!(ConsumableQueue!EventCallback), false, is_internal));
m_loop.registerFD(id, EventMask.read); m_loop.registerFD(id, EventMask.read);
m_loop.setNotifyCallback!(EventType.read)(id, &onEvent); m_loop.setNotifyCallback!(EventType.read)(id, &onEvent);
releaseRef(id); // setNotifyCallback increments the reference count, but we need a value of 1 upon return releaseRef(id); // setNotifyCallback increments the reference count, but we need a value of 1 upon return
@ -83,7 +75,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} else { } else {
// fake missing socketpair support on Windows // fake missing socketpair support on Windows
import std.socket : InternetAddress; import std.socket : InternetAddress;
auto addr = new InternetAddress(0x7F000001, 0); scope addr = new InternetAddress(0x7F000001, 0);
auto s = m_sockets.createDatagramSocketInternal(addr, null, true); auto s = m_sockets.createDatagramSocketInternal(addr, null, true);
if (s == DatagramSocketFD.invalid) return EventID.invalid; if (s == DatagramSocketFD.invalid) return EventID.invalid;
fd[0] = cast(sock_t)s; fd[0] = cast(sock_t)s;
@ -106,18 +98,16 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
} }
m_sockets.receive(s, m_buf, IOMode.once, &onSocketData); m_sockets.receiveNoGC(s, m_buf, IOMode.once, &onSocketData);
// use the second socket as the event ID and as the sending end for // use the second socket as the event ID and as the sending end for
// other threads // other threads
auto id = cast(EventID)fd[1]; auto id = cast(EventID)fd[1];
try { try m_sockets.userData!EventID(s) = id;
synchronized (m_eventsMutex) catch (Exception e) assert(false, e.msg);
m_events[s] = id;
} catch (Exception e) assert(false, e.msg);
// FIXME: avoid dynamic memory allocation for the queue // FIXME: avoid dynamic memory allocation for the queue
m_loop.initFD(id, FDFlags.internal, m_loop.initFD(id, FDFlags.internal,
EventSlot(new ConsumableQueue!EventCallback, false, is_internal, s)); EventSlot(mallocT!(ConsumableQueue!EventCallback), false, is_internal, s));
assert(getRC(id) == 1); assert(getRC(id) == 1);
return id; return id;
} }
@ -142,7 +132,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
final override void trigger(EventID event, bool notify_all) final override void trigger(EventID event, bool notify_all)
shared @trusted { shared @trusted @nogc {
import core.atomic : atomicStore; import core.atomic : atomicStore;
auto thisus = cast(PosixEventDriverEvents)this; auto thisus = cast(PosixEventDriverEvents)this;
assert(event < thisus.m_loop.m_fds.length, "Invalid event ID passed to shared triggerEvent."); assert(event < thisus.m_loop.m_fds.length, "Invalid event ID passed to shared triggerEvent.");
@ -154,7 +144,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
final override void wait(EventID event, EventCallback on_event) final override void wait(EventID event, EventCallback on_event)
{ @nogc {
if (!isInternal(event)) m_loop.m_waiterCount++; if (!isInternal(event)) m_loop.m_waiterCount++;
getSlot(event).waiters.put(on_event); getSlot(event).waiters.put(on_event);
} }
@ -183,13 +173,12 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
version (linux) {} version (linux) {}
else { else {
private void onSocketData(DatagramSocketFD s, IOStatus, size_t, scope RefAddress) private void onSocketData(DatagramSocketFD s, IOStatus, size_t, scope RefAddress)
{ @nogc {
m_sockets.receive(s, m_buf, IOMode.once, &onSocketData); m_sockets.receiveNoGC(s, m_buf, IOMode.once, &onSocketData);
EventID evt;
try { try {
synchronized (m_eventsMutex) EventID evt = m_sockets.userData!EventID(s);
evt = m_events[s]; scope doit = { onEvent(evt); }; // cast to nogc
onEvent(evt); () @trusted { (cast(void delegate() @nogc)doit)(); } ();
} catch (Exception e) assert(false, e.msg); } catch (Exception e) assert(false, e.msg);
} }
} }
@ -201,13 +190,13 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
final override bool releaseRef(EventID descriptor) final override bool releaseRef(EventID descriptor)
{ @nogc {
nogc_assert(getRC(descriptor) > 0, "Releasing reference to unreferenced event FD."); nogc_assert(getRC(descriptor) > 0, "Releasing reference to unreferenced event FD.");
if (--getRC(descriptor) == 0) { if (--getRC(descriptor) == 0) {
if (!isInternal(descriptor)) if (!isInternal(descriptor))
m_loop.m_waiterCount -= getSlot(descriptor).waiters.length; m_loop.m_waiterCount -= getSlot(descriptor).waiters.length;
() @trusted nothrow { () @trusted nothrow {
try .destroy(getSlot(descriptor).waiters); try freeT(getSlot(descriptor).waiters);
catch (Exception e) nogc_assert(false, e.msg); catch (Exception e) nogc_assert(false, e.msg);
} (); } ();
version (linux) { version (linux) {
@ -216,10 +205,6 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
auto rs = getSlot(descriptor).recvSocket; auto rs = getSlot(descriptor).recvSocket;
m_sockets.cancelReceive(rs); m_sockets.cancelReceive(rs);
m_sockets.releaseRef(rs); m_sockets.releaseRef(rs);
try {
synchronized (m_eventsMutex)
m_events.remove(rs);
} catch (Exception e) nogc_assert(false, e.msg);
} }
m_loop.clearFD!EventSlot(descriptor); m_loop.clearFD!EventSlot(descriptor);
version (Posix) close(cast(int)descriptor); version (Posix) close(cast(int)descriptor);
@ -235,9 +220,9 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
private EventSlot* getSlot(EventID id) private EventSlot* getSlot(EventID id)
{ @nogc {
nogc_assert(id < m_loop.m_fds.length, "Invalid event ID."); nogc_assert(id < m_loop.m_fds.length, "Invalid event ID.");
return () @trusted { return &m_loop.m_fds[id].event(); } (); return () @trusted @nogc { return &m_loop.m_fds[id].event(); } ();
} }
private ref uint getRC(EventID id) private ref uint getRC(EventID id)
@ -246,7 +231,7 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
} }
private bool isInternal(EventID id) private bool isInternal(EventID id)
{ @nogc {
return getSlot(id).isInternal; return getSlot(id).isInternal;
} }
} }

View file

@ -34,14 +34,14 @@ alias KqueueEventDriver = PosixEventDriver!KqueueEventLoop;
final class KqueueEventLoop : PosixEventLoop { final class KqueueEventLoop : PosixEventLoop {
private { private {
int m_queue; int m_queue;
kevent_t[] m_changes; size_t m_changeCount = 0;
kevent_t[] m_events; kevent_t[100] m_changes;
kevent_t[100] m_events;
} }
this() this()
@safe nothrow { @safe nothrow @nogc {
m_queue = () @trusted { return kqueue(); } (); m_queue = () @trusted { return kqueue(); } ();
m_events.length = 100;
assert(m_queue >= 0, "Failed to create kqueue."); assert(m_queue >= 0, "Failed to create kqueue.");
} }
@ -57,9 +57,8 @@ final class KqueueEventLoop : PosixEventLoop {
ts.tv_sec = cast(time_t)secs; ts.tv_sec = cast(time_t)secs;
ts.tv_nsec = cast(uint)hnsecs * 100; ts.tv_nsec = cast(uint)hnsecs * 100;
auto ret = kevent(m_queue, m_changes.ptr, cast(int)m_changes.length, m_events.ptr, cast(int)m_events.length, timeout == Duration.max ? null : &ts); auto ret = kevent(m_queue, m_changes.ptr, cast(int)m_changeCount, m_events.ptr, cast(int)m_events.length, timeout == Duration.max ? null : &ts);
m_changes.length = 0; m_changeCount = 0;
m_changes.assumeSafeAppend();
//print("kevent returned %s", ret); //print("kevent returned %s", ret);
@ -97,11 +96,11 @@ final class KqueueEventLoop : PosixEventLoop {
if (edge_triggered) ev.flags |= EV_CLEAR; if (edge_triggered) ev.flags |= EV_CLEAR;
if (mask & EventMask.read) { if (mask & EventMask.read) {
ev.filter = EVFILT_READ; ev.filter = EVFILT_READ;
m_changes ~= ev; putChange(ev);
} }
if (mask & EventMask.write) { if (mask & EventMask.write) {
ev.filter = EVFILT_WRITE; ev.filter = EVFILT_WRITE;
m_changes ~= ev; putChange(ev);
} }
//if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP; //if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP;
} }
@ -111,7 +110,7 @@ final class KqueueEventLoop : PosixEventLoop {
kevent_t ev; kevent_t ev;
ev.ident = fd; ev.ident = fd;
ev.flags = EV_DELETE; ev.flags = EV_DELETE;
m_changes ~= ev; putChange(ev);
} }
override void updateFD(FD fd, EventMask old_mask, EventMask new_mask, bool edge_triggered = true) override void updateFD(FD fd, EventMask old_mask, EventMask new_mask, bool edge_triggered = true)
@ -124,16 +123,26 @@ final class KqueueEventLoop : PosixEventLoop {
ev.filter = EVFILT_READ; ev.filter = EVFILT_READ;
ev.flags = new_mask & EventMask.read ? EV_ADD : EV_DELETE; ev.flags = new_mask & EventMask.read ? EV_ADD : EV_DELETE;
if (edge_triggered) ev.flags |= EV_CLEAR; if (edge_triggered) ev.flags |= EV_CLEAR;
m_changes ~= ev; putChange(ev);
} }
if (changes & EventMask.write) { if (changes & EventMask.write) {
ev.filter = EVFILT_WRITE; ev.filter = EVFILT_WRITE;
ev.flags = new_mask & EventMask.write ? EV_ADD : EV_DELETE; ev.flags = new_mask & EventMask.write ? EV_ADD : EV_DELETE;
if (edge_triggered) ev.flags |= EV_CLEAR; if (edge_triggered) ev.flags |= EV_CLEAR;
m_changes ~= ev; putChange(ev);
} }
//if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP; //if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP;
} }
private void putChange(ref kevent_t ev)
@safe nothrow @nogc {
m_changes[m_changeCount++] = ev;
if (m_changeCount == m_changes.length) {
auto ret = (() @trusted => kevent(m_queue, &m_changes[0], cast(int)m_changes.length, null, 0, null)) ();
assert(ret == 0);
m_changeCount = 0;
}
}
} }

View file

@ -17,7 +17,7 @@ final class SignalFDEventDriverSignals(Loop : PosixEventLoop) : EventDriverSigna
private Loop m_loop; private Loop m_loop;
this(Loop loop) { m_loop = loop; } this(Loop loop) @nogc { m_loop = loop; }
override SignalListenID listen(int sig, SignalCallback on_signal) override SignalListenID listen(int sig, SignalCallback on_signal)
{ {

View file

@ -654,7 +654,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
} }
package DatagramSocketFD adoptDatagramSocketInternal(int socket, bool is_internal = true, bool close_on_exec = false) package DatagramSocketFD adoptDatagramSocketInternal(int socket, bool is_internal = true, bool close_on_exec = false)
{ @nogc {
auto fd = DatagramSocketFD(socket); auto fd = DatagramSocketFD(socket);
if (m_loop.m_fds[fd].common.refCount) // FD already in use? if (m_loop.m_fds[fd].common.refCount) // FD already in use?
return DatagramSocketFD.init; return DatagramSocketFD.init;
@ -742,8 +742,16 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
on_receive_finish(socket, IOStatus.ok, ret, src_addrc); on_receive_finish(socket, IOStatus.ok, ret, src_addrc);
} }
package void receiveNoGC(DatagramSocketFD socket, ubyte[] buffer, IOMode mode, void delegate(DatagramSocketFD, IOStatus, size_t, scope RefAddress) @safe nothrow @nogc on_receive_finish)
@trusted @nogc {
scope void delegate() @safe nothrow do_it = {
receive(socket, buffer, mode, on_receive_finish);
};
(cast(void delegate() @safe nothrow @nogc)do_it)();
}
void cancelReceive(DatagramSocketFD socket) void cancelReceive(DatagramSocketFD socket)
{ @nogc {
assert(m_loop.m_fds[socket].datagramSocket.readCallback !is null, "Cancelling read when there is no read in progress."); assert(m_loop.m_fds[socket].datagramSocket.readCallback !is null, "Cancelling read when there is no read in progress.");
m_loop.setNotifyCallback!(EventType.read)(socket, null); m_loop.setNotifyCallback!(EventType.read)(socket, null);
m_loop.m_fds[socket].datagramSocket.readBuffer = null; m_loop.m_fds[socket].datagramSocket.readBuffer = null;
@ -855,7 +863,7 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets
} }
final override bool releaseRef(SocketFD fd) final override bool releaseRef(SocketFD fd)
{ @nogc {
import taggedalgebraic : hasType; import taggedalgebraic : hasType;
auto slot = () @trusted { return &m_loop.m_fds[fd]; } (); auto slot = () @trusted { return &m_loop.m_fds[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.");

View file

@ -245,7 +245,7 @@ final class PollEventDriverWatchers(Events : EventDriverEvents) : EventDriverWat
} }
this(Events events) this(Events events)
{ @nogc {
m_events = events; m_events = events;
} }