Boost.Threads static linking FYI

I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time: The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions. In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed. Comments? Mike

Michael Glassford wrote:
I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time:
The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions.
In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed.
Comments?
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits. Does anyone see any drawbacks to doing this? Mike

Michael Glassford wrote:
Michael Glassford wrote:
I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time:
The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions.
In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed.
Comments?
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits.
Please explain how if there is an easy method.
Does anyone see any drawbacks to doing this?
The only drawback is the typical one of a thread being killed before it can exit.

Edward Diener wrote:
Michael Glassford wrote:
Michael Glassford wrote:
I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time:
The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions.
In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed.
Comments?
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits.
Please explain how if there is an easy method.
I mean it's easy enough for me to do it in the Boost.Threads code; I meant to ask if anyone thought I should do so, or if there were drawbacks to having the library do it. I guess I forgot to ask.
Does anyone see any drawbacks to doing this?
The only drawback is the typical one of a thread being killed before it can exit.
And the drawback that it only deals with threads created by Boost.Threads; other threads will leak any resources contained in tss. Mike

Michael Glassford wrote:
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits. Does anyone see any drawbacks to doing this?
Would this mechanism be able to deal extraneous on_thread_exit calls due to the user-provided handler calling on_thread_exit (since an implementation I have in mind would have no idea if a thread was Boost thread or not)? Now that you've formed this interface, I plan on submitting an implementation for this function (that I mentioned previously) that I'd expect to work on at least MSVC and future versions of Windows GCC, by the end of the July. Aaron W. LaFramboise

Aaron W. LaFramboise wrote:
Michael Glassford wrote:
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits. Does anyone see any drawbacks to doing this?
Would this mechanism be able to deal extraneous on_thread_exit calls due to the user-provided handler calling on_thread_exit (since an implementation I have in mind would have no idea if a thread was Boost thread or not)?
It should be OK for on_thread_exit to be called multiple times on a thread, and for on_process_exit to be called multiple times as well. The only problem is if one of the calls happens too early (e.g. calling on_thread_exit before the thread is done using tss, or calling on_process_exit before on_thread_exit has been called for all threads). Even if one of the functions gets called too soon the worst thing that should happen is that expected data won't be there or (if on_process_exit gets called before on_thread_exit), leaks.
Now that you've formed this interface, I plan on submitting an implementation for this function (that I mentioned previously) that I'd expect to work on at least MSVC and future versions of Windows GCC, by the end of the July.
Thanks! I was going to ask about it, and look forward to seeing it. Mike

Michael Glassford wrote:
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits. Does anyone see any drawbacks to doing this?
No, as long as it is safe to call the on_thread_exit callback twice. However did you consider the alternative design of void at_thread_exit( void (*pf)() ); (along the lines of atexit).

Peter Dimov wrote: [... working around MS TLS silliness ...] Initiating a "boost.org's" petition to MS requesting production of patches to all their OSes (the status shall be "critical" or whatever they use for most deadly viruses) that would provide support for TSD destructors would be much more productive, really. Just .02 euros. regards, alexander.

Peter Dimov wrote:
Michael Glassford wrote:
Replying to myself: I forgot to mention: it's easy enough to make threads created by Boost.Threads call on_thread_exit() after the thread function exits. Does anyone see any drawbacks to doing this?
No, as long as it is safe to call the on_thread_exit callback twice.
It can, and I've checked in the change.
However did you consider the alternative design of
void at_thread_exit( void (*pf)() );
(along the lines of atexit).
There was already an add_thread_exit() that did this; at_thread_exit is a better name, so I've just checked in the changes to use it. Functions passed to at_thread_exit() are what get called by on_thread_exit(). The dll version of Boost.Threads on Win32 calls on_thread_exit() automatically when a thread exits; in static builds of Boost.Threads, the user is responsible for calling on_thread_exit(), though hopefully this will change in a future Boost.Threads release. Were you suggesting that at_thread_exit be publically exposed as a feature of Boost.Threads on all platforms? Mike

Michael Glassford wrote:
Peter Dimov wrote:
However did you consider the alternative design of
void at_thread_exit( void (*pf)() );
(along the lines of atexit).
There was already an add_thread_exit() that did this; at_thread_exit is a better name, so I've just checked in the changes to use it. Functions passed to at_thread_exit() are what get called by on_thread_exit(). The dll version of Boost.Threads on Win32 calls on_thread_exit() automatically when a thread exits; in static builds of Boost.Threads, the user is responsible for calling on_thread_exit(), though hopefully this will change in a future Boost.Threads release.
Were you suggesting that at_thread_exit be publically exposed as a feature of Boost.Threads on all platforms?
I was suggesting that the DLL version of Boost.Threads should implement at_thread_exit itself. In static builds, the user would be responsible for implementing it (and we can provide a sample implementation in, say, at_thread_exit.dll). This way you won't need the dummy is_tss_implemented function; TSS use will automatically cause link errors. On the other hand, the on_thread_exit callback approach allows us to invoke it automatically from Boost.Threads-created threads. One possibility would be to retain both at_thread_exit and on_thread_exit in DLL builds, but define neither in static builds. But this will cause link errors due to the missing on_thread_exit even in programs that don't use TSS.

Michael Glassford wrote:
I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time:
The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions.
In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed.
Comments?
I like this very much as my reticence to use the thread library was completely based on the fact that it did not have a static lib version. While your tss_cleanup_imnplemented() is clever, I wonder if it is really necessary. The spirit of C++ is usuually to allow the programmer to do the wrong thing at their peril. Enforcing tss_cleanup_implemented just to warn the programmer of something which the documentation should make clear is not something I would do. I assume you mean above that on_thread_exit should be called when a thread exits, in the context of the exiting thread.

Edward Diener wrote:
Michael Glassford wrote:
I've made some changes to the Boost.Threads static linking support on Win32. Previously I had added back support for static linking, but without thread-specific storage classes. Now I've added the thread-specific storage classes back in, and exposed two functions that need to be called at the appropriate time:
The function on_thread_exit() should be called when a thread exists, *in the context of the exiting thread*. The function on_process_exit() should be called when the process exit. If these functions are not called at the appropriate time, leaks may occur. If you know you don't need tss cleanup, of course you can just omit to call these functions.
In addition, Boost.Threads static library on Win32 requires the user of the library to define a function called tss_cleanup_implemented(); if it is not defined, a link error results. The only purpose of this function is as a "link-time assertion": the linker error stating that the function is missing warns the the user of the necessity of calling the cleanup functions. In addition, if Boost.Threads later implements tss cleanup in the static library, the linker's duplicate symbol error should warn the user that their custom implementation is no longer needed.
Comments?
I like this very much as my reticence to use the thread library was completely based on the fact that it did not have a static lib version.
While your tss_cleanup_imnplemented() is clever, I wonder if it is really necessary. The spirit of C++ is usuually to allow the programmer to do the wrong thing at their peril. Enforcing tss_cleanup_implemented just to warn the programmer of something which the documentation should make clear is not something I would do.
Who reads documentation? :) Since the function can be empty, it won't be too much of a burden, I hope. As I also hope to make the Boost.Threads library support tss cleanup itself in the static library in a future release, this requirement should go away, too.
I assume you mean above that on_thread_exit should be called when a thread exits, in the context of the exiting thread.
Yes, that's what I meant. Sorry for the typo. Mike
participants (5)
-
Aaron W. LaFramboise
-
Alexander Terekhov
-
Edward Diener
-
Michael Glassford
-
Peter Dimov