/** Safe concurrency based on std.concurrency. */ module fearless.concurrency; public import std.concurrency: Tid, thisTid; auto spawn(F, A...)(F fn, auto ref A args) { import std.functional: forward; import std.concurrency: spawn_ = spawn; return () @trusted { return spawn_(fn, forward!args); }(); } /** Wraps std.concurrency.send to make sure it's not possible to send a fearless.sharing.Exclusive that is already locked to another thread. */ void send(A...)(Tid tid, auto ref A args) { import fearless.sharing: ExclusiveImpl; import std.functional: forward; import std.concurrency: send_ = send; import std.traits: isInstanceOf, isPointer, PointerTarget; static immutable alreadyLockedException = new Exception("Cannot send already locked Exclusive to another thread"); foreach(ref arg; args) { alias T = typeof(arg); static if(isPointer!T && isInstanceOf!(ExclusiveImpl, PointerTarget!T)) { if(arg.isLocked) throw alreadyLockedException; } } return () @trusted { send_(tid, forward!args); }(); } void receive(T...)(auto ref T ops) { import std.concurrency: receive_ = receive; import std.functional: forward; () @trusted { receive_(forward!ops); }(); } auto receiveOnly(A...)() { import std.concurrency: receiveOnly_ = receiveOnly; return () @trusted { return receiveOnly_!A(); }(); }