Boost logo

Boost Users :

From: bkarsjens (karsjens+yahoo_at_[hidden])
Date: 2001-12-08 18:24:24


The first thing I discovered when trying to get threads working is
that the -mthreads option was not being used in jam. I added the
following to the gcc-tools.jam file. I'm not totally sure it's right
-- it's needed for mingw32, but I don't know if it is necessary for
cygwin.

if $(NT)
{
    flags gcc CFLAGS <threading>multi : -mthreads ;
    flags gcc LINKFLAGS <threading>multi : -mthreads ;
}

Adding that let's gdb actually work on it... It doesn't crash deep in
the bowels of thread exiting in some kernel library routine. Although
it still crashes in on_thread_exit doing handlers->push_front(func).
Actually, it crashes in some STL stuff, but that's I'm not sure why,
I'm not that good with gdb yet.

After digging through the implementation of threadmon.cpp, I realized
that (unless I missed something) on_thread_exit was always called with
the same argument, which is the address of cleanup in tss.cpp.
Therefore all of the stuff in threadmon.cpp for keeping a list of
functions registered with on_thread exit were not really needed, it
would always have a list of the same pointer. So why not just keep
that pointer and call it on thread exit. I also discovered that
DllMain wasn't getting called at all because it wasn't defined as
extern "C". This drastically simplifies threadmon.cpp:

// threadmon.cpp : Defines the entry point for the DLL application.
//

#define BOOST_THREADMON_EXPORTS
#include "threadmon.hpp"

#ifdef BOOST_HAS_WINTHREADS

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from
Windows headers
#include <windows.h>

#ifdef BOOST_MSVC
# pragma warning(disable : 4786)
#endif

typedef void (__cdecl * handler)(void);

namespace
{
        handler exit_handler;
}

#if defined(__BORLANDC__)
#define DllMain DllEntryPoint
#endif

extern "C"
BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID)
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            {
                if (exit_handler)
                                        (*exit_handler)();
            }
            break;
    }
    return TRUE;
}

int on_thread_exit(void (__cdecl * func)(void))
{
        exit_handler = func;
    return 0;
}

#endif // BOOST_HAS_WINTHREADS

Note that the above was not copied directly, but has had some editing.
 I think I transcribed it correctly, but maybe I missed a semicolon or
something.

Also, in tss.cpp, cleanup may be called without any handlers
registered... I'm not sure if this was always the case, or if I
introduced this case, so the cleanup function needs to do an
if(handlers) check before actually trying to call them.

And now the tests pass! Wheee!

One more thing. I'm still not convinced for the need of the dll. The
issue is needing to know when a thread has exited, and I think that
could be done by an object that was destructed in a thread-proxy
function. Since you are already using a thread_proxy function, I'm
wondering if you considered this approach and if so, why you rejected
it.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net