• boost tss.hpp源码分析


    tss.hpp定义了thread_specific_ptr,使用thread local storage 技术

    1.在thread目录下的win32和pthread目录下thread_data.hpp定义了两个重要struct:tss_data_node和thread_data_base

    struct tss_data_node    //tss_data_node对应相应线程
    {
        boost::shared_ptr<boost::detail::tss_cleanup_function> func;  //func是thread_specific_ptr的删除器
        void* value;                              //thread_local_storage value
    
        tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
             void* value_):func(func_),value(value_)
        {}
    };
      typedef boost::shared_ptr<thread_data_base> thread_data_ptr;

    struct BOOST_THREAD_DECL thread_data_base:enable_shared_from_this<thread_data_base> {   thread_data_ptr self;      //shared_ptr<thread_data_base>   pthread_t thread_handle;   boost::mutex data_mutex;   boost::condition_variable done_condition;   boost::mutex sleep_mutex;   boost::condition_variable sleep_condition;   bool done;   bool join_started;   bool joined;   boost::detail::thread_exit_callback_node* thread_exit_callbacks;   std::map<void const*,boost::detail::tss_data_node> tss_data;    //tss local storage ,thread_specific_ptr的this作为key,
                                             //tss_data_node保存thread_specific_ptr的value作为 tss_data的value   pthread_mutex_t* cond_mutex;   pthread_cond_t* current_cond;   typedef std::vector<std::pair<condition_variable*, mutex*>> notify_list_t;   notify_list_t notify;   typedef std::vector<shared_ptr<shared_state_base> > async_states_t;   async_states_t async_states_;   bool interrupt_enabled;   bool interrupt_requested;   thread_data_base():       thread_handle(0),       done(false),join_started(false),joined(false),       thread_exit_callbacks(0),       cond_mutex(0),       current_cond(0),       notify(),       async_states_(), interrupt_enabled(true), interrupt_requested(false)   {}   virtual ~thread_data_base();   typedef pthread_t native_handle_type;   virtual void run()=0;   virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)   {     notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));   }   void make_ready_at_thread_exit(shared_ptr<shared_state_base> as)   {     async_states_.push_back(as);   } };

     

    2. boost::thread类里有个私有指针detail::thread_data_ptr thread_info;说明每个thread都对应了一个thread_data_base

    class thread_data:public detail::thread_data_base
    {
      private:
        F f;  //thread_data继承于thread_data_base并且 f保存函数
    };
    template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
    thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): //thread初始化最多带9个参数
      thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
    {
      start_thread();
    }
    
    explicit thread(BOOST_THREAD_RV_REF(F) f
            //, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
            ):
              thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
            {
                start_thread();
            }

     在start_thread.cpp运行 start_thread_noexcept()

     int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());

    thread_proxy

    static void* thread_proxy(void* param)
                {
                    //boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
                    boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();
                    thread_info->self.reset();
                    detail::set_current_thread_data(thread_info.get());    //调用pthread_setspecific
    #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
                    BOOST_TRY
                    {
    #endif
                        thread_info->run();
    #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    
                    }
                    BOOST_CATCH (thread_interrupted const&)
                    {
                    }
    
                    BOOST_CATCH_END
    #endif
                    detail::tls_destructor(thread_info.get());
                    detail::set_current_thread_data(0);
                    boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
                    thread_info->done=true;
                    thread_info->done_condition.notify_all();
    
                    return 0;
                }

    3.pthread_getspecific和pthread_setspecific。pthread_getpecific和pthread_setspecific实现同一个线程中不同函数间共享数据的一种很好的方式。这里一个线程共享的是

    thread_data_ptr thread_info
    boost::detail::thread_data_base* get_current_thread_data()
    {   boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);   return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key); } void set_current_thread_data(detail::thread_data_base* new_data) { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data)); }

     

    4.tss_cleanup_function

    namespace detail
    {
      struct tss_cleanup_function
       {
         virtual ~tss_cleanup_function()
          {}
    
          virtual void operator()(void* data)=0;
       };
    
       BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
       BOOST_THREAD_DECL void* get_tss_data(void const* key);
    }

    首先定义了一个虚结构体,并重载了运算符()并定义成纯虚函数,tss_cleanup_function可以看成是一个函数对象

    5.delete_data和run_custom_cleanup_function

    struct delete_data: detail::tss_cleanup_function
    {
         void operator()(void* data)
         {
             delete static_cast<T*>(data);
         }
    };
    struct run_custom_cleanup_function:  detail::tss_cleanup_function
    {
      void (*cleanup_function)(T*);
    
      explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):             cleanup_function(cleanup_function_) {} void operator()(void* data) {   cleanup_function(static_cast<T*>(data)); }
    };

     boost::shared_ptr<detail::tss_cleanup_function> cleanup;

    在thread_specific_ptr类里面定义了delete_data和run_custom_cleanup_function,继承tss_cleanup_function,定义运算符(),作用都是清楚 T*data,delete_data是delete T* data,而run_custom_cleaup_function指定函数指针。所以thread_specific_ptr构造时,默认构造函数 shared_ptr cleanup 指向delete_data,构造函数指定函数指针,cleanup初始化为run_custom_cleanup_function对象

    6.以thread_specific_ptr默认构造函数为例

    thread_specific_ptr():
                cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
    {}

    heap_new在堆上生成delete_data对象并返回指针,do_heap_delete指定删除器

    7.set_tss_data和get_tss_data具体实现在win32下boost_1_64_0libs hreadsrcwin32 hread.cpp,Linux在boost_1_64_0/libs/thread/src/pthread/thread.cpp

    void* get_tss_data(void const* key)
    {
         if(tss_data_node* const current_node=find_tss_data(key))
         {
              return current_node->value;
         }
              return NULL;
    }

    void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
    {
      if(tss_data_node* const current_node=find_tss_data(key))
      {
        if(cleanup_existing && current_node->func && (current_node->value!=0))
        {
        (*current_node->func)(current_node->value);
        }
        if(func || (tss_data!=0))
        {
          current_node->func=func;
          current_node->value=tss_data;
        }
        else
        {
          erase_tss_node(key);
        }
      }
      else if(func || (tss_data!=0))
      {
        add_new_tss_node(key,func,tss_data);
      }
     }

    void add_new_tss_node(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data)
    {
      detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
      current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
    }

     

    8. set_tss_data和get_tss_data都会调用find_tss_data(key)来找到tss_data_node,

            tss_data_node* find_tss_data(void const* key)
            {
                detail::thread_data_base* const current_thread_data(get_current_thread_data()); //获得当前线程thread_data_base
                if(current_thread_data)
                {
                    std::map<void const*,tss_data_node>::iterator current_node=
                        current_thread_data->tss_data.find(key);
                    if(current_node!=current_thread_data->tss_data.end())
                    {
                        return &current_node->second;
                    }
                }
                return 0;
            }
     boost::detail::thread_data_base* get_current_thread_data()
     {
       boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
       return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
     }
    
     void set_current_thread_data(detail::thread_data_base* new_data)
     {
       boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
       BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
     }

    总结:

    boost实现tss原理是:每个thread保存一个thread_data_base,thread_data_base里面有tss_map,tss_map将thread_specific_ptr<T>地址作为key,T* new_value保存到

    tss_data_node作为tss_map的value。并且使用pthread_getspecific和pthread_setspecific共享thread里thread_data_base的智能指针 thread_data_ptr thread_info
  • 相关阅读:
    D语言中的Range与C#中IEnumreable的区别
    D语言中使用Curl读取网页
    在D语言中如何调用Windows中的COM控件
    D语言反射
    D语言基本类型判断 traits.d
    Struts2 XML验证器
    (十四)Struts2 验证框架
    (十三)Struts2 发送电子邮件
    (十二)Struts2 数据库访问
    (十一)Struts2 文件上传
  • 原文地址:https://www.cnblogs.com/dj0325/p/9290801.html
Copyright © 2020-2023  润新知