Threads not garbage collected ?
Jonathan M Davis via Digitalmars-d
digitalmars-d at puremagic.com
Tue Feb 21 23:14:27 PST 2017
On Wednesday, February 22, 2017 05:28:17 Alex via Digitalmars-d wrote:
> import core.thread;
>
> class A
> {
> Thread mThread;
> bool mStopped;
>
> this()
> {
> mThread = new Thread(&run);
> mThread.start();
> }
>
> void run()
> {
> while (!mStopped)
> {
> //do stuff
> }
> }
> ~this()
> {
> mStopped = true;
> mThread.join();
> }
> }
>
>
>
> void main()
> {
> auto a = new A;
> delete a; //need this or the program hangs
> }
>
> In both gdc and dmd I need to use manually delete this object or
> the program is blocked after main. Is by design ?
> It seems undesirable, as the thread can be many layers of
> encapsulation down, and they all need manual deletes.
There's never a guarantee that an object is going to be collected. The
program is free to not bother to collect any GC-allocated objects when it
exits. Normally, the GC only attempts to collect objects and free memory
when you call new, because that's when it needs more memory.
And because you put the join in a class finalizer, the thread won't be
joined unless the GC happens to decide to collect that class - which it will
never do, because new isn't being called, and the open thread keeps the
program running.
If you want deterministic or guaranteed destruction, you should use a
struct on the stack, not a class. In general, managing resources in a class
finalizer is just begging for them to never be released, and it should
really only be done as a backup for when the resources aren't explicitly
freed by the programmer.
In this particular case, the program would probably exit if you did
void main()
{
{
auto a = new A;
}
import core.memory;
GC.collect();
}
but really, relying on a class' finalizer to be called in order to join a
thread is begging for trouble.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list