February 22, 2017
Alex wrote:

> The thread can then prevent the program from exiting on exception or otherwise.
> If the garbage collector doesn't kill threads, do I need to break all encapsulation to call some sort of finalise or destroy function on every object in case it has a thread object in it ?
> It would probably be better to have all core.thread.Threads registered in the run time so they can be killed when main exits.
they are registered. but not exiting while at least one thread is alive is deliberate decision.

you may take a look at std.concurrency instead of working with "raw" threads. besides providing services like message passing, it does terminate all the spawned threads if their owner dies. you may change that, of course, this is just a convenient default.

but note that such termination will require calling `receive()` in a spawned thread. still, i think that message passing feature of std.concurrency is so useful that there is no reason to bypass it and invent your own. besides, you may just call `receiveTimeout()` with small timeout (not zero, there *was* a bug with zero == infinity) in your thread even if you aren't using standard message passing mechanics; it is completely harmless.
February 22, 2017
On Wednesday, 22 February 2017 at 05:28:17 UTC, Alex wrote:
> void main()
> {
> 	auto a = new A;
> 	delete a;		//need this or the program hangs
> }
>

https://p0nce.github.io/d-idioms/#The-trouble-with-class-destructors


February 22, 2017
On Wednesday, 22 February 2017 at 14:51:24 UTC, Guillaume Piolat wrote:
> https://p0nce.github.io/d-idioms/#The-trouble-with-class-destructors

eh, I think this is less a destructor issue and just that the thread is still running and thus not eligible for collection anyway - there's still a reference to it elsewhere.
February 22, 2017
On Wednesday, 22 February 2017 at 05:28:17 UTC, Alex wrote:
> [...]
>
> In both gdc and dmd I need to use manually delete this object or the program is blocked after main. Is by design ?

Yes, it's documented here[1] (others have already replied on the GC subject, so I won't go into that). If you want a thread to be forcibly terminated instead of preventing program termination you need to set `thread.isDaemon = true`.

> It seems undesirable, as the thread can be many layers of encapsulation down, and they all need manual deletes.

It's highly desirable to not have the program terminate when there's still work to be done on some critical non-main thread, so the druntime split into daemon vs non-daemon threads makes sense.
Whether new threads should be daemonized by default (as opposed to preventing program termination by default) is an arbitrary decision. In your case, just set `isDaemon = true` for your threads and you should be good.

[1] https://dlang.org/phobos/core_thread.html#.Thread.isDaemon
February 22, 2017
On Wednesday, 22 February 2017 at 15:23:59 UTC, Moritz Maxeiner wrote:
>> It seems undesirable, as the thread can be many layers of encapsulation down, and they all need manual deletes.
>
> It's highly desirable to not have the program terminate when there's still work to be done on some critical non-main thread, so the druntime split into daemon vs non-daemon threads makes sense.
> Whether new threads should be daemonized by default (as opposed to preventing program termination by default) is an arbitrary decision. In your case, just set `isDaemon = true` for your threads and you should be good.
>
> [1] https://dlang.org/phobos/core_thread.html#.Thread.isDaemon

Thanks, that is what I need.
February 23, 2017
The thread you created holds a reference to the `class A` object, so that object can't be collected.

This is what you probably want. As soon as the object is collected, its memory can be reused. But the thread still has a reference to it, so it can modify and read that memory. And whoever the GC handed that memory can modify and read it. In short, data corruption.
February 23, 2017
On Wednesday, 22 February 2017 at 11:29:27 UTC, Alex wrote:
> The point is that the thread object could be 20 layers of encapsulation down in a library.
> The thread could also be added 20 layers down long after the main function was written and tested.
>

Here is what works for me:
- having a clear owner for things that may own resource transitively,
   => an acyclic graph of objects
- use destructors, _but ensure they are called manually not by the GC_,
- in each destructor, call .destroy on every members that are classes (in the right order if it matters),
- call .destroy on the top-level object to exit

It was insane before I did that.
1 2
Next ›   Last »