www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - fearless v0.0.1 - shared made easy (and safe)

reply Atila Neves <atila.neves gmail.com> writes:
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); }();
}
Sep 18
next sibling parent Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 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)

 [...]
Whaaaaaaaaahhhhhh!!!!!! You made my day! /Paolo
Sep 18
prev sibling next sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 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)

 [...]
Why is this is an external 3rd party library isn't of the standard library? -Alexander
Sep 18
next sibling parent shfit <shfit fake.de> writes:
On Tuesday, 18 September 2018 at 17:34:10 UTC, 12345swordy wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves 
 wrote:
 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)

 [...]
Why is this is an external 3rd party library isn't of the standard library? -Alexander
Agreed, this is great!
Sep 18
prev sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 18 September 2018 at 17:34:10 UTC, 12345swordy wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves 
 wrote:
 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)

 [...]
Why is this is an external 3rd party library isn't of the standard library? -Alexander
Because it's far easier to release something with dub. If it gets traction then it might be a candidate for inclusion in Phobos.
Sep 19
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/19/18 6:44 AM, Atila Neves wrote:
 On Tuesday, 18 September 2018 at 17:34:10 UTC, 12345swordy wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 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)

 [...]
Why is this is an external 3rd party library isn't of the standard library?
Because it's far easier to release something with dub. If it gets traction then it might be a candidate for inclusion in Phobos.
I'll also add that if it depends on dip1000, Phobos isn't ready for that anyway. But if Phobos does end up getting to that point, this 100% should be in the standard library. It's a no-brainer. -Steve
Sep 19
prev sibling next sibling parent reply Claude <no no.no> writes:
On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 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.
Beautiful! The only current downside, is the fact the application using that library has to be compiled with -dip1000 if I'm not wrong?
Sep 19
parent Atila Neves <atila.neves gmail.com> writes:
On Wednesday, 19 September 2018 at 07:33:55 UTC, Claude wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves 
 wrote:
 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.
Beautiful! The only current downside, is the fact the application using that library has to be compiled with -dip1000 if I'm not wrong?
Thanks! You only have to compile with -dip1000 if you want guarantees about safety... ;)
Sep 19
prev sibling next sibling parent reply thedeemon <dlang thedeemon.com> writes:
On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:

 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.
Nice! I spent a few minutes playing with the example and trying to break it, make the pointer escape, but I couldn't, the compiler caught me every time. This DIP1000 thing seems to be working!
Sep 19
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Sep 19, 2018 at 10:58:04AM +0000, thedeemon via Digitalmars-d-announce
wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 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.
Nice! I spent a few minutes playing with the example and trying to break it, make the pointer escape, but I couldn't, the compiler caught me every time. This DIP1000 thing seems to be working!
Finally, dip1000 is proving its value. T -- Doubt is a self-fulfilling prophecy.
Sep 19
prev sibling parent reply Guillaume Piolat <spam smam.org> writes:
On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves wrote:
 // compile with -dip1000
 import fearless;
Now *that* is a properly named library :)
Sep 20
parent Atila Neves <atila.neves gmail.com> writes:
On Thursday, 20 September 2018 at 09:52:37 UTC, Guillaume Piolat 
wrote:
 On Tuesday, 18 September 2018 at 17:20:26 UTC, Atila Neves 
 wrote:
 // compile with -dip1000
 import fearless;
Now *that* is a properly named library :)
Thanks! :) I'm still wondering whether or not anyone noticed that I named it that so I could write `import fearless.concurrency`.
Sep 20