$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-08-05 14:31:39
I thought I had sent this yesterday, but it appears that I didn't.
Though it's a little late, here it is anyway.
Roland wrote:
> On Wed, 04 Aug 2004 10:50:47 -0400 Michael Glassford <glassfordm_at_[hidden]> wrote:
>
>
>>Having experimented a bit and thought a bit, here's my take on how this
>>could work:
>>
>>1) Functions on_process_enter() and on_thread_enter() are unnecessary.
>
>
> I am not convinced about on_process_enter. This could be the place to allocate
> the slot without the need for any locking. (and the call to atexit)
I'm not worried about locking. Locking is needed for at_thread_exit(),
since it can be called from multiple threads simultaneously. Since
locking will already be necessary there, it makes sense to use it for
the on_process_*() and on_thread_*() functions, especially since they
are also available for users to call and we can't guarantee they will be
called in a thread-safe manner, either.
>>2) DllMain() and tls_callback() are needed only to call on_thread_exit().
>
>
> I agree on that.
>
>
>>3) Function at_thread_exit() schedules a tss cleanup task that needs to
>>be run for a thread that uses tss. The first time it is executed it also
>>calls:
>>
>> atexit(on_process_exit);
>> atexit(on_thread_exit);
>>
>>to schedule cleanup for the main thread before destructors of global
>>objects are run and to schedule on_process_exit() (which calls TlsFree()).
>
>
> I have some reservations of how you will make sure, that the first call is in
> the context of the main thread. If not the call to atexit might be erreonous.
> (Is atexit really multithread safe?)
Good point. I'll make that modification.
> This is why I schedule the call to atexit within .CRT$XCU.
> (BTW the initialization of the slot could very well also be from this place,
> the choice to do it earlier was only to have the slot well before any constructors
> were run.)
I don't think that's a big problem either if locking is assumed. It
makes as much sense to allocate the slot when it is first used; that way
if Boost.Threads tss is never used a tls slot is never allocated.
>>4) In addition, to provide some cleanup support for compilers that don't
>>yet have tls_callback() support, the thread class continues to call
>>on_thread_exit() after the thread function exits for threads created by
>>Boost.Threads.
>
>
> Yes this is very reasonable. I would even suggest that this is the default behaviour
> and only when the thread is foreign, the callback shall be used.
> However this will require some (thread specific) flag that can be interrogated
> by the tls_callback implementation whether boost already has called on_thread_exit.
> (Or see the comment further below.)
I'm assuming that on_thread_exit can be called multiple times per thread
(as it can with the current implementation). The thread-specific flag is
the tls slot's value: if it's zero, no cleanup is needed.
>>This should make unification of the VC++ 7.1 and 6 versions easier; the
>>only difference would be the startup code needed to call
>>on_tls_prepare(), I believe.
>
>
> I think your original semantics of the three:
> void on_process_enter(void);
> void on_process_exit(void);
> void on_thread_exit(void);
>
> is already perfect.
> void main {
> on_process_enter();
>
> ....
>
> on_process_exit();
> }
>
> and calling from the end of the thread proc:
> on_thread_exit.
>
>
> I personally would like to see the tls implementation exposing only
> these and relying on the compiler specific files doing the rest.
> I can even think of on_thread_exit having an internal one shot flag which
> simply prevent it running multiple times in case e.g. boost.thread and
> the callback (or a user code) is calling in multiple times.
As I said, the tls slot itself essentially does this.
> What do you think?
>
> BTW.: Unification is not so hard at all, given the current version.
> I am just dealing with the different semantics of the initializers.
> Newer ones simply have a return value which may abort initialization
> prematurely. But this is rather trivial to solve for.
OK.
>>Comments?
>>
>>
>>Also, I was wondering: has anyone tried this on VC++ 7.0?
>
>
> Not yet. But I still have a version around on my machine.
> What still puzzles me, that there were reports that the solution
> does not work with __declspec(thread).
> I will dive into this issue (tomorrow) and also the static binding to a user DLL
> which also has to betested out yet.
Let me know what you find out about both of these.
Thanks,
Mike