[dmd-concurrency] draft 4

Sean Kelly sean at invisibleduck.org
Tue Jan 12 06:52:59 PST 2010


On Jan 12, 2010, at 12:45 AM, Andrei Alexandrescu wrote:

> To be found at the usual location:
> 
> http://erdani.com/d/fragment.preview.pdf
> 
> I didn't add a lot of text this time around but I do have a full example of communicating threads. Skip to the last section for explanation. I paste the code below. I think it looks pretty darn cool. Sean, please let me know if it floats your boat.
> 
> import std.concurrency, std.stdio;
> 
> void main() {
>   auto low = 0, high = 1000;
>   auto tid = spawn(&fun);
>   foreach (i; low .. high) {
>      writeln("Main thread: ", message, i);
>      tid.send(thisTid, i);

I haven't been able to come up with any difference in implementation for using an interface vs. a free function that accepts an opaque type for sending messages, so the choice seems largely a matter of how you want the call to look.  I'll admit that I like "send(tid, thisTid, i)" since it matches "receive(...)" but this is a small thing really.

>      enforce(receiveOnly!Tid() == tid);

This could be a wrapper for the usual recvmsg call, so no big deal.  What I'd like to do now that I haven't been able to because of a compiler bug is allow a timeout and catchall receiver to be supplied to the full recvmsg call:

recvmsg( after(5, { writefln( "no message received!" ); },
                  any( (Variant v) { writefln( "got something: %s", v ); } ) );

I guess the "any" wrapper could be dropped for the catchall routine and some special casing could be done inside recvmsg:

recvmsg( (Variant v) {...} );

though I do kind of like that "any" (or whatever it would be called) is obvious at a glance and greppable.

>   }
>   // Signal the other thread
>   tid.send(Tid(), 0);

I've considered having the sender's Tid automatically embedded in every message.  Seems like it's pretty much always wanted, though this would mean not being able to use just any old delegate for receiving messages.  ie. if you have a function already that accepts a Foo then would you want to use that directly or would it be a bother to wrap it in something to throw away the Tid?

Finally, I'd like for recvmsg to accept either a function returning void for "accept any of this type" as well as functions returning a bool for "if returns true, the passed value was a match, if false then not" to allow dynamic pattern matching.  Seems like this should be easily possible with a static if inside the recvmsg loop, but I haven't actually tried it yet.

> }
> 
> void fun() {
>   for (;;) {
>      auto msg = receiveOnly!(Tid, int)();
>      if (!msg[0]) return;

Oh, so this format returns a Tuple for multiple arguments and the value for a single argument?  The Tuple is gone by the time the user code is hit with recvmsg so it would have to rewrap it for receiveOnly, but if that's okay then this would work.  I guess the other option would be a completely separate receiveOnly call instead of a wrapper, which could eliminate the extra work.

>      writeln("Secondary thread: ", msg[1]);
>      msg[0].send(thisTid);
>   }
> }


More information about the dmd-concurrency mailing list