www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mailbox limits and dead/livelocks?

reply "Enerqi" <kelvin.d.ward googlemail.com> writes:
The actors in std.concurrency - in this example it's 
non-deterministic whether the process may or may not hang. I'm 
confused as to why. I have set the mailbox sizes to 1. But the 
message flow seems simple enough. I don't see how the message 
limit of 1 is blocking everything, I am catching Variant messages 
so nothing should be in the mailbox unread.


----------
import core.thread;
import std.algorithm;
import std.concurrency;
import std.stdio;

int main(string[] args)
{
     Tid[2] tids;
     bool[Tid] response_flags;
     for(auto i=0; i < 2; ++i)
     {
	tids[i] = spawn(&blah1, thisTid);		
         response_flags[tids[i]] = false;
     }

     auto receive_count = 0;
	
     setMaxMailboxSize(thisTid, 1, OnCrowding.block);
	
     while(! reduce!"a && b"(response_flags))
     {
	writeln(response_flags, " ", receive_count);
         receive((Tid some_blah_id, int done)
                 {					
                     assert(done == 42);
                     ++receive_count;
                     response_flags[some_blah_id] = true;					
                 },
                 (Variant v)
                 {
                     writeln("Unexpected message: ", v, " type ", 
v.type());
                 }
                 );		
     }

     return 0;
}

void blah1(Tid parent)
{
     setMaxMailboxSize(thisTid, 1, OnCrowding.block);
     auto subtid = spawn(&subsub, thisTid, parent);

     send(subtid, thisTid, false);
     receive((bool got)
	    {
	        assert(got);
	    },
	    (Variant v)
	    {
                 writeln("Unexpected message: ", v, " type ", 
v.type());
             });
     send(subtid, thisTid, 10);
     receive((int got)
	    {
	        assert(got == 11);
	    },
	    (Variant v)
	    {
                 writeln("Unexpected message: ", v, " type ", 
v.type());
             });
}

void subsub(Tid parent, Tid grandparent)
{
     setMaxMailboxSize(thisTid, 1, OnCrowding.block);
     receive((Tid parent, bool whatever)
             {
	        assert(!whatever);
	    },
	    (Variant v)
	    {
                 writeln("Unexpected message: ", v, " type ", 
v.type());
             });
     send(parent, true);
     receive((Tid parent, int n)
             {
                 assert(n == 10);
	    },
	    (Variant v)
	    {
                 writeln("Unexpected message: ", v, " type ", 
v.type());
             });
     send(parent, 11);

     send(grandparent, parent, 42);
}

----------


Cheers.
Jul 24 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/24/2012 07:46 AM, Enerqi wrote:
 The actors in std.concurrency - in this example it's non-deterministic
 whether the process may or may not hang. I'm confused as to why. I have
 set the mailbox sizes to 1. But the message flow seems simple enough. I
 don't see how the message limit of 1 is blocking everything, I am
 catching Variant messages so nothing should be in the mailbox unread.

I have struggled with a similar problem recently. When an apparent lock-up occurs, it may be because a worker has terminated, likely by assert(). (There has been a thread about exceptions from workers getting lost.) The trick is to start the worker with spawnLinked so that a LinkTerminated exception can be received on the owner's side: tids[i] = spawnLinked(&blah1, thisTid); // ... (LinkTerminated exc) { writeln("A worker has terminated: ", exc); // ... }, The other std.concurrency exception that can be received as a message is OwnerTerminated: (OwnerTerminated exc) { writeln("The owner has terminated; exiting."); isDone = true; } I am in the process of updating the following page with the information above: http://ddili.org/ders/d.en/concurrency.html Ali
Jul 24 2012
parent "Enerqi" <kelvin.d.ward googlemail.com> writes:
Excellent, it was a rogue exception in another program that was 
causing hangs and issues for me. Thanks :)

On Tuesday, 24 July 2012 at 15:33:34 UTC, Ali Çehreli wrote:
 On 07/24/2012 07:46 AM, Enerqi wrote:
 The actors in std.concurrency - in this example it's

non-deterministic
 whether the process may or may not hang. I'm confused as to

why. I have
 set the mailbox sizes to 1. But the message flow seems simple

enough. I
 don't see how the message limit of 1 is blocking everything,

I am
 catching Variant messages so nothing should be in the mailbox

unread. I have struggled with a similar problem recently. When an apparent lock-up occurs, it may be because a worker has terminated, likely by assert(). (There has been a thread about exceptions from workers getting lost.) The trick is to start the worker with spawnLinked so that a LinkTerminated exception can be received on the owner's side: tids[i] = spawnLinked(&blah1, thisTid); // ... (LinkTerminated exc) { writeln("A worker has terminated: ", exc); // ... }, The other std.concurrency exception that can be received as a message is OwnerTerminated: (OwnerTerminated exc) { writeln("The owner has terminated; exiting."); isDone = true; } I am in the process of updating the following page with the information above: http://ddili.org/ders/d.en/concurrency.html Ali

Jul 24 2012