Skip to content

Commit

Permalink
Merge pull request #208 from vibe-d/dip1000
Browse files Browse the repository at this point in the history
Fix compatibility with DIP1000
  • Loading branch information
s-ludwig authored Sep 22, 2022
2 parents 6c5f719 + 2c98288 commit f42a57c
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 39 deletions.
5 changes: 5 additions & 0 deletions dub.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,8 @@ configuration "libasync" {
configuration "generic" {
// Defines eventDriver as the generic EventDriver interface. Setup must be done manually.
}

buildType "unittest-dip1000" {
buildOptions "unittests" "debugMode" "debugInfo"
dflags "-preview=dip1000"
}
2 changes: 2 additions & 0 deletions run-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ fi

dub test --arch=$ARCH --compiler=$DC -c $CONFIG

dub test --arch=$ARCH --compiler=$DC -c $CONFIG -b unittest-dip1000

if [ ${BUILD_EXAMPLE=1} -eq 1 ]; then
for ex in $(\ls -1 examples/*.d); do
echo "[INFO] Building example $ex"
Expand Down
4 changes: 2 additions & 2 deletions source/eventcore/drivers/posix/dns.d
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ final class EventDriverDNS_GHBN(Events : EventDriverEvents, Signals : EventDrive
scope addr = new RefAddress(() @trusted { return cast(sockaddr*)&sa; } (), sa.sizeof);
RefAddress[1] aa;
aa[0] = addr;
on_lookup_finished(handle, DNSStatus.ok, aa);
on_lookup_finished(handle, DNSStatus.ok, () @trusted { return aa[]; } ()); // NOTE DIP-1000 doesn't allow this, even if the parameter is scope
} break;
case AF_INET6: {
sockaddr_in6 sa;
Expand All @@ -407,7 +407,7 @@ final class EventDriverDNS_GHBN(Events : EventDriverEvents, Signals : EventDrive
scope addr = new RefAddress(() @trusted { return cast(sockaddr*)&sa; } (), sa.sizeof);
RefAddress[1] aa;
aa[0] = addr;
on_lookup_finished(handle, DNSStatus.ok, aa);
on_lookup_finished(handle, DNSStatus.ok, () @trusted { return aa[]; } ()); // NOTE DIP-1000 doesn't allow this, even if the parameter is scope
} break;
}

Expand Down
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 @@ -895,10 +895,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
10 changes: 7 additions & 3 deletions source/eventcore/drivers/winapi/core.d
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,13 @@ 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));
@nogc {
m_ioEvents.filterPending!((evt) @safe {
foreach (ovl; overlapped)
if (ovl is evt.overlapped)
return false;
return true;
});
}

private void executeThreadCallbacks()
Expand Down
2 changes: 1 addition & 1 deletion source/eventcore/drivers/winapi/dns.d
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class WinAPIEventDriverDNS : EventDriverDNS {
scope addr = new RefAddress(() @trusted { return cast(sockaddr*)&sa; } (), addrlen);
RefAddress[1] addrs;
addrs[0] = addr;
on_lookup_finished(id, DNSStatus.ok, addrs);
on_lookup_finished(id, DNSStatus.ok, () @trusted { return addrs[]; } ()); // NOTE DIP-1000 doesn't allow this, even if the parameter is scope
return id;
}

Expand Down
2 changes: 1 addition & 1 deletion source/eventcore/drivers/winapi/sockets.d
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ final class WinAPIEventDriverSockets : EventDriverSockets {

if (!isValid(socket)) return false;

switch (multicast_address.addressFamily) {
switch (() @trusted { return multicast_address.addressFamily; } ()) { // DIP-1000: addressFamily's this is not considered scope
default: assert(false, "Multicast only supported for IPv4/IPv6 sockets.");
case AddressFamily.INET:
struct ip_mreq {
Expand Down
4 changes: 2 additions & 2 deletions source/eventcore/internal/consumablequeue.d
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ final class ConsumableQueue(T)
m_first = m_first & m_capacityMask;
}

private ref T getPendingAt(size_t idx)
private scope ref T getPendingAt(size_t idx)
{
assert(idx < m_pendingCount, "Pending item index out of bounds.");
return m_storage[(m_first + m_consumedCount + idx) & m_capacityMask].value;
Expand Down Expand Up @@ -251,7 +251,7 @@ unittest {


void filterPending(alias pred, T)(ConsumableQueue!T q)
{
@safe {
size_t ir = 0;
size_t iw = 0;

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 f42a57c

Please sign in to comment.