Multi-Thread message passing approach

Charles Hixson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Aug 14 18:53:33 PDT 2016


Looking at the std.concurrency code, it appears that Tid is just a 
handle to a class, so multiple assignments should all refer to the same 
underlying class, and it looks like that underlying class (MessageBox) 
uses mutexes to ensure safe handling of multiple access.  So this shared 
access to tids should be safe.  But in that case why can't Tids be 
passed as function parameters to spawn, which would have avoided the 
requirement for a fixed length shared array?  So I don't trust my 
reasoning here.

If I modify the code to attempt to pass a Tid[] as a member of struct 
Start I get:

/usr/include/dmd/phobos/std/concurrency.d(603): Error: static assert  
"Aliases to mutable thread-local data not allowed."
test.d(47):        instantiated from here: send!(Start)

and this seems to imply that the casting away of shared might also be an 
unsafe access which just doesn't happen to be detected by the library.

On 08/14/2016 07:44 AM, Charles Hixson via Digitalmars-d-learn wrote:
> This is an approach to n x n thread message passing. The idea is that 
> each thread should be able to pass messages to any other thread.  The 
> only alternative I've come up with involves the main thread handling 
> each message.  Is that a better approach?  Is there a better way to 
> pass lists of Tids?
>
> import    std.concurrency;
> import    std.stdio;
>
> import    core.thread;
>
> shared    Tid[3]    tidList;
>
> struct    Start    {    int    dummy    =    0;    }
> struct    Msg    {    int    orig;    int    dest;    }
> struct    Done    {    int    dummy    =    0;    }
>
> void    worker (int ndx)
> {
>     writeln    ("worker ", ndx, " spawned");
>     {  auto    msg    =    receiveOnly!(Start)();
>         writeln    ("worker ", ndx, " started");
>     }
>     Tid[]    tids;
>     foreach    (t; tidList)    {    tids    ~=    cast(Tid)t;    }
>     for    (int i = 0;    i < 3;    i++)
>     {   if    (i != ndx)
>         {  Msg msg    =    Msg(ndx, i);
>             send (tids[i], msg);
>         }
>     }
>     writeln    ("worker ", ndx, " got tidList");
>     bool    done    =    false;
>     while    (!done)
>     {  receive
>         (   (Msg msg)    {    writeln ("msg from: ", msg.orig, ", to: 
> ", msg.dest);    },
>             (Done d)        {    done = true;    }
>         );
>     }
>     writeln ("worker ", ndx, " is done");
> }
>
> void    main()
> {
>     Start    start;
>     Done    done;
>     for    (int i = 0;    i < 3;    i++)
>     {  auto tid    =    spawn (&worker, i);
>         tidList[i]    =    cast(shared Tid)tid;
>     }
>     foreach (i; 0 .. 3)    {    send (cast(Tid)tidList[i], start);    }
>     Thread.sleep (1000.msecs);
>     foreach (i; 0 .. 3)    {    send (cast(Tid)tidList[i], done);    }
>     Thread.sleep (1000.msecs);
>     writeln ("main is done");
> }
>
>



More information about the Digitalmars-d-learn mailing list