View mode: basic / threaded / horizontal-split · Log in · Help
June 23, 2012
Strange exception using threads
I am using a secondary thread to send messages to it so it can 
print those messages.

import std.stdio;
import std.concurrency;

void main()
{
	auto low = 0, high = 10;
	
	auto tid = spawn(&writer);
	
	foreach(i; low..high)
	{
		writeln("Main thread: ", i);
		tid.send(tid, i);
	}
}

void writer()
{
	while( true )
	{
		receive(
			(Tid id, int i)
			{
				writeln("Secondary thread: ", i);
			}
		);
	}
}

This is the result:
Main thread: 0
Main thread: 1
Main thread: 2
Main thread: 3
Main thread: 4
Main thread: 5
Main thread: 6
Main thread: 7
Main thread: 8
Main thread: 9
Secondary thread: 0
Secondary thread: 1
Secondary thread: 2
Secondary thread: 3
Secondary thread: 4
Secondary thread: 5
Secondary thread: 6
Secondary thread: 7
Secondary thread: 8
Secondary thread: 9
std.concurrency.OwnerTerminated@std/concurrency.d(248): Owner 
terminated
----------------
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool 
std.concurrency.MessageBox.get!(void 
function(std.concurrency.Tid, int)*).get(scope void 
function(std.concurrency.Tid, int)*).bool onControlMsg(ref 
std.concurrency.Message)+0x2a) [0x437016]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool 
std.concurrency.MessageBox.get!(void 
function(std.concurrency.Tid, int)*).get(scope void 
function(std.concurrency.Tid, int)*).bool scan(ref 
std.concurrency.List!(std.concurrency.Message).List)+0x68) 
[0x437084]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool 
std.concurrency.MessageBox.get!(void 
function(std.concurrency.Tid, int)*).get(scope void 
function(std.concurrency.Tid, int)*)+0x88) [0x436c20]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void 
std.concurrency.receive!(void function(std.concurrency.Tid, 
int)*).receive(void function(std.concurrency.Tid, int)*)+0x32) 
[0x436b86]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void 
main.writer()+0x13) [0x43066b]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(_D3std11concurrency11__T6_spawnZ6_spawnFbPFZvZS3std11concurrency3Tid4execMFZv+0x45) 
[0x430941]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void 
core.thread.Thread.run()+0x2a) [0x4470fe]
/home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(thread_entryPoint+0xf3) 
[0x446e97]

The program runs correctly but then boom! Does anyone know why?
June 23, 2012
Re: Strange exception using threads
On Sat, 23 Jun 2012 18:05:47 +0200, Minas Mina  
<minas_mina1990@hotmail.co.uk> wrote:

> I am using a secondary thread to send messages to it so it can print  
> those messages.
>
> import std.stdio;
> import std.concurrency;
>
> void main()
> {
> 	auto low = 0, high = 10;
> 	
> 	auto tid = spawn(&writer);
> 	
> 	foreach(i; low..high)
> 	{
> 		writeln("Main thread: ", i);
> 		tid.send(tid, i);
> 	}
> }
>
> void writer()
> {
> 	while( true )
> 	{
> 		receive(
> 			(Tid id, int i)
> 			{
> 				writeln("Secondary thread: ", i);
> 			}
> 		);
> 	}
> }
>
> This is the result:
> Main thread: 0
> Main thread: 1
> Main thread: 2
> Main thread: 3
> Main thread: 4
> Main thread: 5
> Main thread: 6
> Main thread: 7
> Main thread: 8
> Main thread: 9
> Secondary thread: 0
> Secondary thread: 1
> Secondary thread: 2
> Secondary thread: 3
> Secondary thread: 4
> Secondary thread: 5
> Secondary thread: 6
> Secondary thread: 7
> Secondary thread: 8
> Secondary thread: 9
> std.concurrency.OwnerTerminated@std/concurrency.d(248): Owner terminated
> ----------------
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool  
> std.concurrency.MessageBox.get!(void function(std.concurrency.Tid,  
> int)*).get(scope void function(std.concurrency.Tid, int)*).bool  
> onControlMsg(ref std.concurrency.Message)+0x2a) [0x437016]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool  
> std.concurrency.MessageBox.get!(void function(std.concurrency.Tid,  
> int)*).get(scope void function(std.concurrency.Tid, int)*).bool scan(ref  
> std.concurrency.List!(std.concurrency.Message).List)+0x68) [0x437084]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(bool  
> std.concurrency.MessageBox.get!(void function(std.concurrency.Tid,  
> int)*).get(scope void function(std.concurrency.Tid, int)*)+0x88)  
> [0x436c20]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void  
> std.concurrency.receive!(void function(std.concurrency.Tid,  
> int)*).receive(void function(std.concurrency.Tid, int)*)+0x32) [0x436b86]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void  
> main.writer()+0x13) [0x43066b]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(_D3std11concurrency11__T6_spawnZ6_spawnFbPFZvZS3std11concurrency3Tid4execMFZv+0x45)  
> [0x430941]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(void  
> core.thread.Thread.run()+0x2a) [0x4470fe]
> /home/minas/Projects/D/D_Test/D_Test/bin/Debug/D_Test(thread_entryPoint+0xf3)  
> [0x446e97]
>
> The program runs correctly but then boom! Does anyone know why?

You can notify child threads that their owner terminates so they can  
finish up

import std.stdio;
import std.concurrency;

void main()
{
	auto low = 0, high = 10;
	
	auto tid = spawnLinked(&writer);
	
	foreach(i; low..high)
	{
		writeln("Main thread: ", i);
		tid.send(tid, i);
	}
    writeln("need to gracefully terminate child threads");
    tid.send(tid, Term());
    writeln("term sent");
}

struct Term {}
void writer()
{
    bool done;
	while( !done )
	{
		receive(
			(Tid id, int i)
			{
				writeln("Secondary thread: ", i);
			},
            (Tid id, Term term)
            {
                writeln("Owner terminated, so do we");
                done = true;
            }
		);
	}
}


Main thread: 0
Main thread: 1
Main thread: 2
Main thread: 3
Main thread: 4
Secondary thread: 0
Secondary thread: 1
Secondary thread: 2
Secondary thread: 3
Secondary thread: 4
Main thread: 5
Main thread: 6
Main thread: 7
Main thread: 8
Main thread: 9
Secondary thread: 5
Secondary thread: 6
need to gracefully terminate child threads
term sent
Secondary thread: 7
Secondary thread: 8
Secondary thread: 9
Owner terminated, so do we
June 23, 2012
Re: Strange exception using threads
On 06/23/2012 09:05 AM, Minas Mina wrote:
> I am using a secondary thread to send messages to it so it can print
> those messages.

> std.concurrency.OwnerTerminated@std/concurrency.d(248): Owner terminated

The OwnerTerminated exception is thrown when a worker attempts to 
receive a message to notify it about the fact that its owner has been 
terminated.

There are ways to deal with the situation:

- The worker can catch this particular exception

- The worker can catch this exception as a message

- The owner can send a special YouAreDone :) message to the worker so it 
no longer attempts to receive messages and exits gracefully

- More?

Here is the second method as described in TDPL's concurrency chapter, 
which is available online:

  http://www.informit.com/articles/article.aspx?p=1609144

void writer()
{
    bool done = false;

    while( !done )
    {
        receive(
            (Tid id, int i)
            {
                writeln("Secondary thread: ", i);
            },

            (OwnerTerminated exc) // <----- as a message
            {
                done = true;
            }
        );
    }
}

Ali

-- 
D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
June 23, 2012
Re: Strange exception using threads
On Sat, 23 Jun 2012 18:29:37 +0200, simendsjo <simendsjo@gmail.com> wrote:

> 	auto tid = spawnLinked(&writer);

auto tid = spawn(&writer); of course
June 23, 2012
Re: Strange exception using threads
On Sat, 23 Jun 2012 18:29:50 +0200, Ali Çehreli <acehreli@yahoo.com> wrote:

>         receive(
>             (Tid id, int i)
>             {
>                 writeln("Secondary thread: ", i);
>             },
>              (OwnerTerminated exc) // <----- as a message
>             {
>                 done = true;
>             }
>         );

Nice. I thought you had to send an explicit message.
June 23, 2012
Re: Strange exception using threads
Thank you very much :)

I like the "you are done :)" approach!
June 24, 2012
Re: Strange exception using threads
On Jun 23, 2012, at 9:31 AM, simendsjo <simendsjo@gmail.com> wrote:

> On Sat, 23 Jun 2012 18:29:37 +0200, simendsjo <simendsjo@gmail.com> wrote:
> 
>>    auto tid = spawnLinked(&writer);
> 
> auto tid = spawn(&writer); of course

With spawnLinked the child will send a termination message to the parent as well.
Top | Discussion index | About this forum | D home