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
next sibling parent =?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
prev sibling 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

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

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

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

 catching Variant messages so nothing should be in the mailbox

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