fearless v0.0.1 - shared made easy (and @safe)

Atila Neves atila.neves at gmail.com
Tue Sep 18 17:20:26 UTC 2018


The `shared` keyword currently means one of two things:

1. You can use core.atomic with it
2. It's some struct and you BYOM (Bring Your Own Mutex)


Do you have to send mutable data to other threads? Are you tired 
of locking a mutex and casting? Now you don't have to:


https://code.dlang.org/packages/fearless


I was envious of std::sync::Mutex from Rust and thought: can I 
use DIP1000 to make this work in D and be @safe? Turns out, yes.

I'm going to write a blog post about this explaining the why and 
how. I'm too tired right now though, so here's some code:


// compile with -dip1000
import fearless;


struct Foo {
     int i;
}

int* gEvilInt;


void main() @safe {

     // create an instance of Exclusive!Foo allocated on the GC 
heap
     auto foo = gcExclusive!Foo(42);
     // from now the value inside `foo` can only be used by 
calling `lock` (a.k.a. `borrow`)

     {
         int* oldIntPtr; // only here to demostrate scopes, see 
below
         auto xfoo = foo.lock();  // get exclusive access to the 
data (this locks a mutex)

         safeWriteln("i: ", xfoo.i);
         xfoo.i = 1;
         safeWriteln("i: ", xfoo.i);

         // can't escape to a global
         static assert(!__traits(compiles, gEvilInt = &xfoo.i));

         // ok to assign to a local that lives less
         int* intPtr;
         static assert(__traits(compiles, intPtr = &xfoo.i));

         // not ok to assign to a local that lives longer
         static assert(!__traits(compiles, oldIntPtr = &xfoo.i));
     }

     // Demonstrate sending to another thread and mutating
     auto tid = spawn(&func, thisTid);
     tid.send(foo);
     receiveOnly!Ended;
     safeWriteln("i: ", foo.lock.i);
}

struct Ended{}

void func(Tid tid) @safe {
     receive(
         (Exclusive!Foo* m) {
             auto xfoo = m.lock;
             xfoo.i++;
         },
     );

     tid.send(Ended());
}

// for some reason the writelns here are all @system
void safeWriteln(A...)(auto ref A args) {
     import std.stdio: writeln;
     import std.functional: forward;
     () @trusted { writeln(forward!args); }();
}



More information about the Digitalmars-d-announce mailing list