From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-06-04 15:51:30
"Malcolm Noyes" <boost_at_[hidden]> wrote in message
> > unless I can implement tss cleanup properly on
> >Win32 (which I haven't proved yet) the static library option would
> >have to disappear again on Win32.
> There are 3 possible ways that I'm aware of to attempt to fix this
> problem, although all have their drawbacks. I've tested at least 2
> them on some samples so I know that in principle they work, but I
> haven't had enough time to test these to identify all the issues.
> 3 methods that I know of are:
> i) At the first use of tss data, start a new thread to wait on the
> original thread handle. The theory is that when the original thread
> ends, the handle gets signaled, the 'watchdog' thread wakes up and
> cleans up the tss data for the original thread. An obvious
> optimisation is to have a watchdog class that can wait for several
> threads per instance (up to 63 since you'd have to have an event [or
> similar] to 'wake up' the thread when you wanted to add a new thread
> handle to wait for). This sounds easy but the optimisation
> complicates the implementation, as does the possibility that you
> be waiting on a thread that doesn't end until after 'main' has ended
> (maybe the thread is joined in a static destructor). This is the
> solution that I tried first and I recall that there was some problem
> with termination that made it unworkable, but I'm sure that it
> be possible. The idea of a watchdog has of course been mentioned
> before ;-)
This is an interesting approach, and worth looking into in spite of
the problems you mention.
> ii) Implement a thread watchdog via a dll using thread detach. This
> is the idea that Michael referred to that Roland proposed. I
> tried this for 2 reasons; first it *requires* the distribution of a
Actually, if I understand it correctly, the whole point of Roland's
approach is that it doesn't require the distribution of a dll. The
"dll" was created on-the-fly by the Boost.Thread code.
> and I'm aware from my own experience how difficult that is in
> some organisations from a political and logistical point of view.
> Second, there are things that you can't do in DllMain, for example
> MSDN mentions this: "Calling Win32 functions other than TLS,
> object-creation, and file functions may result in problems that are
> difficult to diagnose" (as usual with MS documentation, it's not
> whether this restriction applies to DLL_THREAD_DETACH). So whilst
> would be possible to create a dll that had a 'C' interface (so that
> could 'LoadLibrary' easily) and provided a callback for a cleanup
> function (passing a thread id so that we can use it to lookup in a
> and perform the cleanup), there may be (i.e. probably will be)
> restrictions on what 'cleanup' might be allowed to do, so basically
> any non-trivial cleanup (e.g. calling socket functions) would not be
This is a good point.
> iii) Implement a 'cleanup guard' as part of the thread function.
> Basically this means that we have an object that is responsible for
> managing the lifetime of the tss data and the lifetime of the guard
> object is limited by the 'scope' of the thread function (i.e. an
> instance of an object is declared at the beginning of the thread
> function and the destructor cleans up). Clearly this is easy to
> implement automatically for boost initialised threads, and would
> probably also be possible for use of tss data in the primary thread
> (i.e dynamic initialisation of statics and 'main') by introducing a
> static. That would leave 'adopted' threads which would have to
> declare an instance of the guard object to be able to use tss data.
> This solution has the advantage of simplicity (it's trivial to
> implement the allocation and cleanup of the tss data using a vector,
> for example) but has the disadvantage that it would require a change
> to the published interface for tss data - users of adopted threads
> with tss data requirements have to declare an instance of the guard
> manage the scope of the tss data. It also has one other significant
> advantage IMO, which is that it should be possible to allow each new
> instance of the guard to manage all tss data for the thread until it
> gets destroyed, which would allow for an instance of the guard to be
> declared in a functor that was passed to a thread pool. This would
> mean that tss data used by functors when a thread pool thread
> the function would be cleaned up when the *functor* exits, not when
> the thread exits (which conceptually may never happen). This seems
> me to be a more sensible place to apply the cleanup that when the
> thread exits.
> I'm trying to pull together a test implementation of all three
> - if I ever get there I'll post the results . . .
I'd be very interested in the results.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk