Thread overview
'importing' threads — i.e. thread_attachThis()
Aug 12, 2016
Cauterite
Aug 12, 2016
Guillaume Piolat
Aug 12, 2016
Guillaume Piolat
Aug 12, 2016
Cauterite
August 12, 2016
I'm planning on 'importing' a thread into the D runtime using thread_attachThis(), and was just wondering about the potential pitfalls of this process. For example:

- Would having an entry function other than core.thread.thread_entryPoint() pose problems? What about during stack unwinding? Should I try to replicate the exception handling code of thread_entryPoint() in my own entry function?

- I'm aware of having to invoke rt_moduleTlsCtor() explicitly, but what about rt_moduleTlsDtor() ? Should I again follow thread_entryPoint()'s behaviour here?

- How important is it to run the thread though _beginthreadex() ? I know the Microsoft CRT uses _beginthreadex()/_threadstartex() to set up the thread's '_tiddata' object, but since D uses the Digital Mars _beginthreadex (which I don't have source for) I'm not entirely sure what goes on in there. It *appears* to be messing around with a global '__thdtbl' object.

- Do I need to call thread_detachThis() when the thread terminates, or can I just wait until the corresponding Thread object gets destroyed by the GC?



I'm using DMD on Windows x32 by the way.

Thanks for your help.
August 12, 2016
On Friday, 12 August 2016 at 10:45:22 UTC, Cauterite wrote:
>
> - Would having an entry function other than core.thread.thread_entryPoint() pose problems?

No.


> What about during stack unwinding?

It doesn't need runtime or attachment.

> Should I try to replicate the exception handling code of thread_entryPoint() in my own entry function?

If you control the whole lifetime of the thread, probably so.

> - I'm aware of having to invoke rt_moduleTlsCtor() explicitly, but what about rt_moduleTlsDtor() ? Should I again follow thread_entryPoint()'s behaviour here?

Same answer.
Two cases: you create and destroy the threads (which seem to be your case) or you just get callbacks.

> - How important is it to run the thread though _beginthreadex() ? I know the Microsoft CRT uses _beginthreadex()/_threadstartex() to set up the thread's '_tiddata' object, but since D uses the Digital Mars _beginthreadex (which I don't have source for) I'm not entirely sure what goes on in there. It *appears* to be messing around with a global '__thdtbl' object.

In Windows circle I've heard that beginthreadex was necessary but I don't remember why.

> - Do I need to call thread_detachThis() when the thread terminates, or can I just wait until the corresponding Thread object gets destroyed by the GC?

- Whole lifetime case:
You don't necessarily need to. When the runtime terminate (Runtime.terminate()) every thread will be detached.

- Callback case:
You may have problems if one of the registered thread is destroyed outside of your program and then the GC tries to stop it though. For this reason if you are in the callback case you can try to detach it on exit.


August 12, 2016
On Friday, 12 August 2016 at 18:59:35 UTC, Guillaume Piolat wrote:
> - Callback case:
> You may have problems if one of the registered thread is destroyed outside of your program and then the GC tries to stop it though. For this reason if you are in the callback case you can try to detach it on exit.

For anyone reading this, consider using a RAII struct in the case of a foreign callback (typically: shared library). You can find one ready-to-use here: https://github.com/AuburnSounds/dplug/blob/master/core/dplug/core/runtime.d#L92
August 12, 2016
On Friday, 12 August 2016 at 18:59:35 UTC, Guillaume Piolat wrote:
> On Friday, 12 August 2016 at 10:45:22 UTC, Cauterite wrote:
>>

Thanks, this is very helpful. I already feel much more confident about the idea.

My use is definitely the 'whole-lifetime' case, so I might be able to get away with ignoring the `_beginthreadex` business since at this stage I won't be using CRT functions anyway.

The only reason I can't run through _beginthreadex normally is because I'm allocating the thread stack myself, which requires use of NtCreateThread.