Thread overview
Strange exception using threads
Jun 23, 2012
Minas Mina
Jun 23, 2012
simendsjo
Jun 23, 2012
simendsjo
Jun 24, 2012
Sean Kelly
Jun 23, 2012
Ali Çehreli
Jun 23, 2012
simendsjo
Jun 23, 2012
Minas Mina
June 23, 2012
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
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
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
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
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
Thank you very much :)

I like the "you are done :)" approach!
June 24, 2012
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.