www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - thread destruction

reply Derek Parnell <derek psych.ward> writes:
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
Dec 02 2005
parent reply Sean Kelly <sean f4.ca> writes:
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
Dec 02 2005
parent reply Derek Parnell <derek psych.ward> writes:
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
Dec 02 2005
parent reply John Demme <me teqdruid.com> writes:
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
Dec 03 2005
parent reply Derek Parnell <derek psych.ward> writes:
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
Dec 03 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"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
Dec 06 2005
parent reply Derek Parnell <derek psych.ward> writes:
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
Dec 06 2005
parent reply Don Clugston <dac nospam.com.au> writes:
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.
Dec 06 2005
parent Sean Kelly <sean f4.ca> writes:
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
Dec 07 2005