修改BOOST(一)

    技术2022-05-11  152

    修改BOOST()

     

        boost是个不错的库。可是也不算太成熟。例如,boost的处理TLS是通过boost_threadmon.dll,使用了TLS的代码必须带一个动态链接库;其次库也不能自动安装,也不能根据你的程序选择了什么样的链接方式(MT,MD)选择库,如果每次编写一个小型的测试程序都要设置很多东西,恐怕太费力气了;第三,缺乏一些常用的功能,如事件,读写锁等。今天我要设置的是使得你在VC下只需要设置MTMD方式(链接到多线程动态链接和静态连接库)就可以使用boost。其次是将boost_threadmon.dll合并到libboost_thread.lib库中。『本人刚学boost4天,说错了恐怕在所难免,请指正。本文中使用的版本为1.28.0

     

    boost多线程库包括两个,一个是boost_threadmon.dll,是个动态连接库,另一个为libboost_thread.lib,是个静态链接库。为什么要用两个呢?主要是为了清除TLS中的数据。在boost_threadmon.dll加载的时候,动态链接库收到消息DLL_PROCESS_ATTACH,这时它分配一个TLS和关键代码段CriticalSection。在用户程序创建线程的时候,收到DLL_THREAD_ATTACH,这时将该线程的TLS数据清除。当主程序退出的时候,收到DLL_PROCESS_DETACH,这时动态链接库清除主线程的TLS数据。

     

    Boost管理TLS如下:当用户设置TLS数据时,boost将该数据指针和一个清理函数放置到一个cleanup_info的结构中,并将它设置到一个cleanup_handlermap中。cleanup_info第一个成员为清理函数指针,第二个成员为数据指针本身。而cleanup_handler则以TLS索引为key,以cleanup_infodata项内部的一个TLS索引对应着一个cleanup_handlers指针,而该指针中的数据都是用户分配的TLS和对应的数据指针以及释放函数。Boost又使用on_thread_exit(&cleanup)函数将cleanup_handlers安装到boost_threadmon.dll中的TLS索引上。

    涉及的tss.cpp中的结构如下:

     

        typedef std::pair<void(*)(void*), void*> cleanup_info;

        typedef std::map<int, cleanup_info> cleanup_handlers;

     

    涉及的threadmon.cpp中的结构如下:

    typedef void (__cdecl * handler)(void);

    typedef std::list<handler> exit_handlers;

    typedef std::set<exit_handlers*> registered_handlers;

     

    上面可能我根本没有说清楚,可是我不想再打太多的字了,下面直接修改:

    1. Thread.hpp文件开头修改为:

    #ifndef BOOST_THREAD_WEK070601_HPP

    #define BOOST_THREAD_WEK070601_HPP

    /*

    ·monitor库:使用/MT       boost_mon_libmt.lib        thread:boost_thread_libmt.lib

    ·monitor库:使用/MTD       boost_mon_libmtd.lib       thread:boost_thread_libmtd.lib

    ·monitor库:使用/MD       boost_mon_libmd.lib       thread:boost_thread_libmd.lib

    ·monitor库:使用/MDD   boost_mon_libmdd.lib       thread:boost_thread_libmdd.lib

     

    ·monitor-thread合并库:使用/MT              boost_thread_mon_libmt.lib       

    ·monitor-thread合并库:使用/MTD       boost_thread_mon_libmtd.lib    

    ·monitor-thread合并库:使用/MD              boost_thread_mon_libmd.lib

    ·monitor-thread合并库:使用/MDD          boost_thread_mon_libmdd.lib    

    */

     

    #ifdef WIN32

           #ifndef  _MT

                  #error ERROR: Must compiled with multithread dll!

           #endif

     

           #define BOOST_HAS_THREADS

           #ifndef BOOST_THREADMON_AS_DLL

                  #ifdef _DEBUG

                         #ifdef _DLL

                                #pragma comment( lib, "boost_thread_mon_libmdd.lib")

                         #else

                                #pragma comment( lib, "boost_thread_mon_libmtd.lib")

                         #endif

                  #else

                         #ifdef _DLL

                                #pragma comment( lib, "boost_thread_mon_libmd.lib")

                         #else

                                #pragma comment( lib, "boost_thread_mon_libmt.lib")

                         #endif

                  #endif

           #else

                  #ifdef _DEBUG

                         #ifdef _DLL

                                #pragma comment( lib, "boost_mon_libmdd.lib")

                                #pragma comment( lib, "boost_thread_libmdd.lib")

                         #else

                                #pragma comment( lib, "boost_mon_libmtd.lib")

                                #pragma comment( lib, "boost_thread_libmtd.lib")

                         #endif

                  #else

                         #ifdef _DLL

                                #pragma comment( lib, "boost_mon_libmd.lib")

                                #pragma comment( lib, "boost_thread_libmd.lib")

                         #else

                                #pragma comment( lib, "boost_mon_libmt.lib")

                                #pragma comment( lib, "boost_thread_libmt.lib")

                         #endif

                  #endif

           #endif

    #endif

    //

     

    #include <boost/config.hpp>

    #ifndef BOOST_HAS_THREADS

    #   error   Thread support is unavailable!

    #endif

     

    2. Threadmon.hpp文件修改为:

    ///

    //2002.5.30修改。

    #ifdef BOOST_THREADMON_AS_DLL

           #ifdef BOOST_THREADMON_EXPORTS

                  #define BOOST_THREADMON_API __declspec(dllexport)

           #else

                  #define BOOST_THREADMON_API __declspec(dllimport)

           #endif

    #else

           #define BOOST_THREADMON_API 

    #endif

     

     

    extern "C" BOOST_THREADMON_API int on_thread_exit(void (__cdecl * func)(void));

    extern "C" BOOST_THREADMON_API void on_thread_detach();

     

    3. Threadmon.cpp文件修改为:

    ///

    //This File has been modified!

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

    //

    //2002.5.30.modified.

    #ifdef BOOST_THREADMON_AS_DLL

    #define BOOST_THREADMON_EXPORTS

    #else

    #include <boost/thread/once.hpp>

    #endif//BOOST_THREADMON_AS_DLL

     

    #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

     

    #include <list>

    #include <set>

    #include <algorithm>

     

    typedef void (__cdecl * handler)(void);

    typedef std::list<handler> exit_handlers;

    typedef std::set<exit_handlers*> registered_handlers;

     

    namespace

    {

        CRITICAL_SECTION cs;

        DWORD key;

        registered_handlers registry;

    }

     

     

    void on_process_attach()

    {

    InitializeCriticalSection(&cs);

    key = TlsAlloc();

    }

     

     

    void on_process_detach()

    {

    on_thread_detach();

        // Destroy any remaining exit handlers.  Above we assumed there'd only be the main

        // thread left, but to insure we don't get memory leaks we won't make that assumption

        // here.

        EnterCriticalSection(&cs);

        for (registered_handlers::iterator it = registry.begin();

    it != registry.end(); ++it)

    {

    #ifndef BOOST_THREADMON_AS_DLL

            for (exit_handlers::iterator p = (*it)->begin(); p != (*it)->end(); ++p)

                (*p)();

    #endif

            delete (*it);

    }

        LeaveCriticalSection(&cs);

        DeleteCriticalSection(&cs);

        TlsFree(key);

    }

     

     

    #ifdef BOOST_THREADMON_AS_DLL

     

     

    #if defined(__BORLANDC__)

    #define DllMain DllEntryPoint

    #endif

     

    extern "C"

    BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID)

    {

        switch (reason)

        {

            case DLL_PROCESS_ATTACH:

            on_process_attach();

                break;

            case DLL_THREAD_ATTACH:

                break;

            case DLL_THREAD_DETACH:

            on_thread_detach();

                break;

            case DLL_PROCESS_DETACH:

            on_process_detach();

                break;

        }

        return TRUE;

    }

     

    #else//BOOST_THREADMON_AS_DLL

     

    boost::once_flag once = BOOST_ONCE_INIT;

     

    class process_envelope

    {

    process_envelope()

    {

    boost::call_once(&on_process_attach, once);

    }

    public:

    ~process_envelope(){on_process_detach();}

    static process_envelope *get()

    {

    static process_envelope p;

    return &p;

    }

    };

     

    #endif//!BOOST_THREADMON_AS_DLL

     

    void on_thread_detach()

    {

        // Call the thread's exit handlers.

    #ifndef BOOST_THREADMON_AS_DLL

    process_envelope::get();

    #endif

        exit_handlers* handlers = static_cast<exit_handlers*>(TlsGetValue(key));

        if (handlers)

        {

            for (exit_handlers::iterator it = handlers->begin(); it != handlers->end(); ++it)

                (*it)();

     

            // Remove the exit handler list from the registered lists and then destroy it.

            EnterCriticalSection(&cs);

            registry.erase(handlers);

            LeaveCriticalSection(&cs);

            delete handlers;

        }

    }

     

    int on_thread_exit(void (__cdecl * func)(void))

    {

    #ifndef BOOST_THREADMON_AS_DLL

    process_envelope::get();

    #endif

        // Get the exit handlers for the current thread, creating and registering

        // one if it doesn't exist.

        exit_handlers* handlers = static_cast<exit_handlers*>(TlsGetValue(key));

        if (!handlers)

        {

            try

            {

                handlers = new exit_handlers;

                // Handle "broken" implementations of operator new that don't throw.

                if (!handlers)

                    return -1;

            }

            catch (...)

            {

                return -1;

            }

     

            // Attempt to set a TLS value for the new handlers.

            if (!TlsSetValue(key, handlers))

            {

                delete handlers;

                return -1;

            }

     

            // Attempt to register this new handler so that memory can be properly

            // cleaned up.

            try

            {

                EnterCriticalSection(&cs);

                registry.insert(handlers);

                LeaveCriticalSection(&cs);

            }

            catch (...)

            {

                LeaveCriticalSection(&cs);

                delete handlers;

                return -1;

            }

        }

     

        // Attempt to add the handler to the list of exit handlers. If it's been previously

        // added just report success and exit.

        try

        {

            handlers->push_front(func);

        }

        catch (...)

        {

            return -1;

        }

     

        return 0;

    }

     

    #endif // BOOST_HAS_WINTHREADS

     

    4. Thread.cpp文件修改为:

    #include "timeconv.inl"行后:

    //2002.5.30;修改

    #ifdef WIN32

           #ifndef BOOST_THREADMON_AS_DLL

           #include "threadmon.hpp"

           #endif

    #endif

     

                  修改thread_proxy(void* param)方法的尾部为:

    //2002.5.30;修改

    #ifdef WIN32

           #ifndef BOOST_THREADMON_AS_DLL

           on_thread_detach();

           #endif

    #endif

     

    5. <boost>/libs/thread/src目录下的所有文件插入到自己新建的工程中,按上面的thread.hpp头文件中的库名分别生成不同的库文件,将这些库文件拷贝到VC目录下,以后编译使用了boost.thread的工程时,再也不需要任何设置了。

     

     

     

     

     

     


    最新回复(0)