修改BOOST(二)

类别:编程语言 点击:0 评论:0 推荐:
  修改BOOST(二)

 

boost提供的thread_specific_ptr用起来很简便。但是TLS的可用索引数量是有限的。特别是在的DLL中,如果第一个进程加载的DLL模块用去了n个索引,第二个进程加载相同模块时可用索引就减少n个,Windows下可用的索引也就一千个左右(我没有去查资料,只是凭记忆写的,如果有错误,可以在下面的讨论中指出,不过大概是这个意思)。不过可以只用一个TLS索引来保存所有的与线程相关的数据。下面是源代码。

1.头文件vtss.hpp

//vtss.hpp。虚拟TSS索引

#ifndef _VTSS_H

#define _VTSS_H

#include <boost/thread/tss.hpp>

 

 

namespace boost {

 

    namespace detail {

        class vtss

        {

        public:

            vtss(void (*cleanup)(void*)=0);

            ~vtss();

 

            void* get() const;

            bool set(void* value);

 

        private:

                     unsigned int key;

        };

 

    }

 

template <typename T>

class vthread_specific_ptr : private noncopyable

{

public:

    vthread_specific_ptr() : m_tss(&thread_specific_ptr<T>::cleanup) { }

 

    T* get() const { return static_cast<T*>(m_tss.get()); }

    T* operator->() const { return get(); }

    T& operator*() const { return *get(); }

    T* release() { T* temp = get(); m_tss.set(0); return temp; }

    void reset(T* p=0) { T* cur = get(); if (cur == p) return; delete cur; m_tss.set(p); }

 

private:

    static void cleanup(void* p) { delete static_cast<T*>(p); }

 

    mutable detail::vtss m_tss;

};

 

} // namespace boost

 

 

#endif

 

  2.vtss.cpp文件

#include <boost/thread/tss.hpp>

#include <boost/thread/vtss.hpp>

#include <boost/thread/mutex.hpp>

#include <map>

#include <set>

 

namespace {

 

       class cleanup_info

       {

       public:

              cleanup_info(void (*_cleanup)(void *)=0,void *_data=0)

                     :cleanup(_cleanup),data(_data){}

              ~cleanup_info(){if(cleanup && data)cleanup(data);}

              void reset(){data=0;}

              void (*cleanup)(void *);

              void *data;

       };

 

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

 

       boost::thread_specific_ptr<cleanup_handlers> ptr_global;

 

       class tsskey

       {

              tsskey();

       public:

              static tsskey &instance();

              unsigned int alloc();

              void free(int key);

 

              boost::mutex m_lock;

              std::set<unsigned int> allkey;

              unsigned int key;

       };

 

       tsskey::tsskey():key(0)

       {

       }

 

       tsskey &tsskey::instance()

       {

              static tsskey tss;

              return tss;

       }

 

       unsigned int tsskey::alloc()

       {

              boost::mutex::scoped_lock lock(m_lock);

              while(allkey.find(++key)!=allkey.end());

              return key;

       }

 

       void tsskey::free(int key)

       {

              boost::mutex::scoped_lock lock(m_lock);

              allkey.erase(key);

       }

      

}

 

namespace boost {

 

       namespace detail {

 

              vtss::vtss(void (*cleanup)(void*))

                     :m_cleanup(cleanup)

              {

                     m_key=tsskey::instance().alloc();

              }

 

              vtss::~vtss()

              {

                     tsskey::instance().free(m_key);

              }

 

              void* vtss::get() const

              {

                     cleanup_handlers *p=ptr_global.get();

                     if(p)

                     {

                            cleanup_handlers::iterator it=p->find(m_key);

                            if(it!=p->end())

                            {

                                   return it->second.data;

                            }

                     }

                     return 0;

              }

 

              void vtss::set(void* value)

              {

                     cleanup_handlers *p=ptr_global.get();

                     if(!p)

                     {

                            p=new cleanup_handlers;

                            ptr_global.reset(p);

                     }

 

                     if(value)

                     {

                            cleanup_info info(m_cleanup, value);

                            (*p)[m_key]=info;

                            info.reset();

                     }

                     else

                     {

                            p->erase(m_key);

                     }

              }

 

       } // namespace detail

 

} // namespace boost

 

   3.Vtss.hpp文件放到<boost>/boost/thread/目录下,vtss.cpp文件放到<boost>/libs/thread/src。它们的用法和原先的pthread_specific_ptr的唯一区别是多了个“v”,也就是vpthread_specific_ptr。另外,还可以将vpthread_specific_ptr的private noncopyable去掉,这时如果你的vpthread_specific_ptr在类对象里面,则该类对象也可以互相复制。

    其次的实现是读写锁,下回吧。

本文地址:http://com.8s8s.com/it/it29628.htm