Skip to content

Commit

Permalink
Change nogc workarounds to work for older compiler versions.
Browse files Browse the repository at this point in the history
  • Loading branch information
s-ludwig committed Sep 11, 2022
1 parent e8e0893 commit 2c98288
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 30 deletions.
20 changes: 13 additions & 7 deletions source/eventcore/drivers/posix/events.d
Original file line number Diff line number Diff line change
Expand Up @@ -171,18 +171,24 @@ final class PosixEventDriverEvents(Loop : PosixEventLoop, Sockets : EventDriverS
trigger(event, cnt > 0);
}
} else {
private void onSocketData(DatagramSocketFD s, IOStatus st, size_t, scope RefAddress)
private void onSocketData(DatagramSocketFD socket, IOStatus st, size_t, scope RefAddress)
@nogc {
// avoid infinite recursion in case of errors
if (st == IOStatus.ok)
m_sockets.receiveNoGC(s, m_buf, IOMode.once, &onSocketData);
m_sockets.receiveNoGC(socket, m_buf, IOMode.once, &onSocketData);

try {
EventID evt = m_sockets.userData!EventID(s);
scope doit = {
trigger(evt, (cast(long[])m_buf)[0] > 1);
}; // cast to nogc
() @trusted { (cast(void delegate() @nogc)doit)(); } ();
EventID evt = m_sockets.userData!EventID(socket);
// FIXME: push @nogc further down the call chain instead of
// performing this ugly workaround
static struct S {
PosixEventDriverEvents this_;
EventID evt;
bool all;
void doit() { this_.trigger(evt, all); }
}
scope s = S(this, evt, (cast(long[])m_buf)[0] > 1);
() @trusted { (cast(void delegate() @nogc)&s.doit)(); } ();
} catch (Exception e) assert(false, e.msg);
}
}
Expand Down
17 changes: 13 additions & 4 deletions source/eventcore/drivers/posix/sockets.d
Original file line number Diff line number Diff line change
Expand Up @@ -889,10 +889,19 @@ final class PosixEventDriverSockets(Loop : PosixEventLoop) : EventDriverSockets

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)();
// FIXME: push @nogc further down the call chain instead of
// performing this ugly workaround
static struct S {
PosixEventDriverSockets this_;
DatagramSocketFD socket;
ubyte[] buffer;
IOMode mode;
void delegate(DatagramSocketFD, IOStatus, size_t, scope RefAddress) @safe nothrow @nogc on_receive_finish;
void doit() { this_.receive(socket, buffer, mode, on_receive_finish); }

}
scope s = S(this, socket, buffer, mode, on_receive_finish);
(cast(void delegate() @safe nothrow @nogc)&s.doit)();
}

void cancelReceive(DatagramSocketFD socket)
Expand Down
64 changes: 45 additions & 19 deletions source/eventcore/internal/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@ import taggedalgebraic;
void print(ARGS...)(string str, ARGS args)
@trusted @nogc nothrow {
import std.format : formattedWrite;
StdoutRange r;
scope cb = () {
try (&r).formattedWrite(str, args);
catch (Exception e) assert(false, e.msg);
};
(cast(void delegate() @nogc @safe nothrow)cb)();
r.put('\n');
// NOTE: formattedWrite isn't @nogc, although it could be for the types that
// we actually log. Since printing is only enabled in debug settings,
// @nogc is artificailly enforced here to be able to provice a @nogc
// API.
static struct S {
string str;
ARGS args;
StdoutRange r;
void doit()
{
try (&r).formattedWrite(str, args);
catch (Exception e) assert(false, e.msg);
}
}
scope s = S(str, args);
(cast(void delegate() @nogc @safe nothrow)&s.doit)();
s.r.put('\n');
}

T mallocT(T, ARGS...)(ARGS args)
Expand Down Expand Up @@ -75,10 +85,14 @@ void freeNT(T)(ref T[] arr)
}

private void noGCDestroy(T)(ref T t)
@trusted {
@trusted @nogc {
// FIXME: only do this if the destructor chain is actually nogc
scope doit = { destroy(t); };
(cast(void delegate() @nogc)doit)();
static struct S {
T* pt;
void doit() { destroy(*pt); }
}
scope s = S(&t);
(cast(void delegate() @nogc)&s.doit)();
}

private extern(C) Throwable.TraceInfo _d_traceContext(void* ptr = null);
Expand All @@ -94,15 +108,27 @@ void nogc_assert(bool cond, string message, string file = __FILE__, int line = _
assert(false);
}

scope doit = {
stderr.writefln("Assertion failure @%s(%s): %s", file, line, message);
stderr.writeln("------------------------");
if (auto info = _d_traceContext(null)) {
foreach (s; info)
stderr.writeln(s);
} else stderr.writeln("no stack trace available");
};
(cast(void delegate() @nogc)doit)(); // write and _d_traceContext are not nogc
// NOTE: writefln isn't @nogc, although it could be for the types that
// we actually log. Since this is only called right before app
// termination, enforcing @nogc is done here to allow keeping the
// API @nogc.
static struct S {
string message;
string file;
int line;
void doit()
{
stderr.writefln("Assertion failure @%s(%s): %s", file, line, message);
stderr.writeln("------------------------");
if (auto info = _d_traceContext(null)) {
foreach (s; info)
stderr.writeln(s);
} else stderr.writeln("no stack trace available");
}

}
scope s = S(message, file, line);
(cast(void delegate() @nogc)&s.doit)(); // write and _d_traceContext are not nogc
}
}

Expand Down

0 comments on commit 2c98288

Please sign in to comment.