Thread overview
thread destruction
Dec 02, 2005
Derek Parnell
Dec 02, 2005
Sean Kelly
Dec 03, 2005
Derek Parnell
Dec 03, 2005
John Demme
Dec 03, 2005
Derek Parnell
Dec 07, 2005
Walter Bright
Dec 07, 2005
Derek Parnell
Dec 07, 2005
Don Clugston
Dec 07, 2005
Sean Kelly
December 02, 2005
Using the following program ...

=================
import std.thread;
import std.stdio;
import std.c.windows.windows;

class athread : Thread
{
    this ()
    {
        super(&thread_main);
        writefln("create thread");
    }

    ~this()
    {
        writefln("destroy thread");
    }

    int thread_main ()
    {
        Sleep(500);
        return 0;
    }

}

int main (char[][] args)
{
    athread m0 = new athread;
    m0.start();
    if(args.length > 1)
    {
        while (m0.getState == Thread.TS.RUNNING){}
        m0.wait();
        if(args.length > 2)
            writefln("done");
    }
    else
    {
        m0.wait();
    }

    return 0;
}
=================

and running it thus ...

=========================
c:\temp>build test4
Path and Version : D:\UTIL\build.exe v2.9(1197)
  built on Wed Aug 10 11:03:42 2005
f:\dmd\bin\..\..\dm\bin\link.exe
test4,test4.exe,,user32+kernel32,test4.def/noi;


c:\temp>test4
create thread
destroy thread

c:\temp>test4 1
create thread

c:\temp>test4 1 2
create thread
done
destroy thread

c:\temp>

=========================

it would appear that the thread destructor doesn't get called if I wait on its state before finishing the program, *unless* I also call writefln().

-- 
Derek Parnell
Melbourne, Australia
3/12/2005 9:27:00 AM
December 02, 2005
Derek Parnell wrote:
> Using the following program ...
...
> it would appear that the thread destructor doesn't get called if I wait on
> its state before finishing the program, *unless* I also call writefln().

Thread objects are not deleted explicitly when they terminate as something may have a reference to them.  Instead, they're garbage collected like everything else.  Have you tried adding a call to fullCollect() before exiting main?


Sean
December 03, 2005
On Fri, 02 Dec 2005 14:35:17 -0800, Sean Kelly wrote:

> Derek Parnell wrote:
>> Using the following program ...
> ...
>> it would appear that the thread destructor doesn't get called if I wait on its state before finishing the program, *unless* I also call writefln().
> 
> Thread objects are not deleted explicitly when they terminate as something may have a reference to them.  Instead, they're garbage collected like everything else.  Have you tried adding a call to fullCollect() before exiting main?

Maybe I didn't make it clear enough. Sometimes their destructor is called when the program exits and sometimes they are not. It all depends on two things:

(1) The destructor is called when the program exits, if I *DO NOT* use the
getState() call.

(2) The destructor is called when the program exits, if I *DO* use the
getState() call but only if I also call writefln().

-- 
Derek Parnell
Melbourne, Australia
3/12/2005 4:36:43 PM
December 03, 2005
Derek Parnell wrote:

> On Fri, 02 Dec 2005 14:35:17 -0800, Sean Kelly wrote:
> 
>> Derek Parnell wrote:
>>> Using the following program ...
>> ...
>>> it would appear that the thread destructor doesn't get called if I wait on its state before finishing the program, *unless* I also call writefln().
>> 
>> Thread objects are not deleted explicitly when they terminate as something may have a reference to them.  Instead, they're garbage collected like everything else.  Have you tried adding a call to fullCollect() before exiting main?
> 
> Maybe I didn't make it clear enough. Sometimes their destructor is called when the program exits and sometimes they are not. It all depends on two things:
> 
> (1) The destructor is called when the program exits, if I *DO NOT* use the
> getState() call.
> 
> (2) The destructor is called when the program exits, if I *DO* use the
> getState() call but only if I also call writefln().
> 

So?  It's irrelevant.  There is no guarantee that a destructor will or will not be called, since there's no guarantee that a class will or will not be collected.  You may find the behavior of the GC to be a little unusual, but as far as I can tell, it's behaving to spec.  I'll admit, however, that this GC behavior sounds a little weird.  getState() must to something more than just return a value.

~John Demme
December 03, 2005
On Sat, 03 Dec 2005 03:45:02 -0500, John Demme wrote:

> Derek Parnell wrote:
> 
>> On Fri, 02 Dec 2005 14:35:17 -0800, Sean Kelly wrote:
>> 
>>> Derek Parnell wrote:
>>>> Using the following program ...
>>> ...
>>>> it would appear that the thread destructor doesn't get called if I wait on its state before finishing the program, *unless* I also call writefln().
>>> 
>>> Thread objects are not deleted explicitly when they terminate as something may have a reference to them.  Instead, they're garbage collected like everything else.  Have you tried adding a call to fullCollect() before exiting main?
>> 
>> Maybe I didn't make it clear enough. Sometimes their destructor is called when the program exits and sometimes they are not. It all depends on two things:
>> 
>> (1) The destructor is called when the program exits, if I *DO NOT* use the
>> getState() call.
>> 
>> (2) The destructor is called when the program exits, if I *DO* use the
>> getState() call but only if I also call writefln().
>> 
> 
> So?  It's irrelevant.

That depends on whether this behaviour is according to the specification or not.

> There is no guarantee that a destructor will or will
> not be called, since there's no guarantee that a class will or will not be
> collected.

Are you saying that the official specification states that when a program completes, i.e. main() exits, that D may *or* may not call the class' destructor function?

> You may find the behavior of the GC to be a little unusual, but as far as I can tell, it's behaving to spec.

If this is so, does it mean that D recommends that for every class instance that is constructed, the coder needs to explicitly call its destructor because D might not get around to it? BTW, I notice that even 'auto' fails in this instance too.

I can understand that this behaviour for some types of resources held by an object, such as RAM, GDI handles, file handles, ... would be okay because the operating system takes responsibility in cleaning these up. But there are other types of resources that the operating system doesn't know about, such as database locking, transaction back-outs, remote servers, ...

This behaviour will be the cause of many calls to a help desk in future.

> I'll admit, however, that
> this GC behavior sounds a little weird.  getState() must to something more
> than just return a value.

... but it doesn't ... weird, as you say. And why would calling writefln()
affect it?


-- 
Derek Parnell
Melbourne, Australia
4/12/2005 9:19:40 AM
December 07, 2005
"Derek Parnell" <derek@psych.ward> wrote in message news:1qadhbehg1olk$.zlet5a2vr2zj$.dlg@40tude.net...
> ... but it doesn't ... weird, as you say. And why would calling writefln()
> affect it?

writefln() affects what is on the stack. The GC is conservative; if something looks like a reference to the data, the data is not free'd.

The general rule with destructors is that they are only guaranteed to be called for:

1) auto objects
2) when an explicit 'delete' is called on it


December 07, 2005
On Tue, 6 Dec 2005 20:13:03 -0800, Walter Bright wrote:

> "Derek Parnell" <derek@psych.ward> wrote in message news:1qadhbehg1olk$.zlet5a2vr2zj$.dlg@40tude.net...
>> ... but it doesn't ... weird, as you say. And why would calling writefln()
>> affect it?
> 
> writefln() affects what is on the stack. The GC is conservative; if something looks like a reference to the data, the data is not free'd.
> 
> The general rule with destructors is that they are only guaranteed to be called for:
> 
> 1) auto objects
> 2) when an explicit 'delete' is called on it

Therefore, to be on the safe side, as we might know what resources an object might hold, we should *always* use either auto or explicit deletes.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"A learning experience is one of those things that says,
 'You know that thing you just did? Don't do that.'" - D.N. Adams
7/12/2005 4:06:05 PM
December 07, 2005
Derek Parnell wrote:
> On Tue, 6 Dec 2005 20:13:03 -0800, Walter Bright wrote:
> 
> 
>>"Derek Parnell" <derek@psych.ward> wrote in message
>>news:1qadhbehg1olk$.zlet5a2vr2zj$.dlg@40tude.net...
>>
>>>... but it doesn't ... weird, as you say. And why would calling writefln()
>>>affect it?
>>
>>writefln() affects what is on the stack. The GC is conservative; if
>>something looks like a reference to the data, the data is not free'd.
>>
>>The general rule with destructors is that they are only guaranteed to be
>>called for:
>>
>>1) auto objects
>>2) when an explicit 'delete' is called on it
> 
> 
> Therefore, to be on the safe side, as we might know what resources an
> object might hold, we should *always* use either auto or explicit deletes.

AFAIK, that applies to any garbage collection scheme.  For example, .NET finalisers are not guaranteed to be called. It does leave me a bit baffled as to what purpose a finaliser can serve.
December 07, 2005
Don Clugston wrote:
> 
> AFAIK, that applies to any garbage collection scheme.  For example, .NET finalisers are not guaranteed to be called. It does leave me a bit baffled as to what purpose a finaliser can serve.

Languages built with GC in mind are a bit better off because the GC can use type information to only scan pointers, rather than things that might be pointers.  This reduces the number of dead objects over time, though some still occur.


Sean