zoukankan      html  css  js  c++  java
  • BOOST 线程完全攻略

     

    本文假设读者已经基本了解boost线程库的使用方法。
    boost是个开源工程,线程这一块也在不断完善之中,到现在这个阶段,boost::thread仅仅实现了一个完美的技术框架,但是读者在实际使用中会发现一些新的技术问题:
    1.boost::thread::join开启一个线程以后,怎样主动结束子线程?
    2.boost线程之间怎样实现消息传递?
    作者在这里描述怎样一步步扩展这些功能。
     
    一. Janitor 异常安全处理
      本文的janitor.hpp是针对异常安全处理的封装类,在后面的扩展类里面有使用到,异常安全的目的是为了保证程序的一段事务的完整性,关于异常安全不是本文的重点,感兴趣的话可以参见http://dev.csdn.net/article/6/6883.shtm
    1. // janitor.hpp : 安全执行类库
    2. //
    3. #pragma once
    4. #include <list>
    5. template <class T>
    6. class RefHolder
    7. {
    8.         T& ref_;
    9. public:
    10.         RefHolder(T& ref) : ref_(ref) {}
    11.         operator T& () const 
    12.         {
    13.                 return ref_;
    14.         }
    15. private:
    16.     // Disable assignment - not implemented
    17.     RefHolder& operator=(const RefHolder&);
    18. };
    19. template <class T>
    20. inline RefHolder<T> ByRef(T& t)
    21. {
    22.         return RefHolder<T>(t);
    23. }
    24. class ScopeGuardImplBase
    25. {
    26.         ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
    27. protected:
    28.         ~ScopeGuardImplBase()
    29.         {
    30.         }
    31.         ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 
    32.                 : dismissed_(other.dismissed_)
    33.         {
    34.                 other.Dismiss();
    35.         }
    36.         template <typename J>
    37.         static void SafeExecute(J& j) throw() 
    38.         {
    39.                 if (!j.dismissed_)
    40.                         try
    41.                         {
    42.                                 j.Execute();
    43.                         }
    44.                         catch(...)
    45.                         {
    46.                         }
    47.         }
    48.         
    49.         mutable bool dismissed_;
    50. public:
    51.         ScopeGuardImplBase() throw() : dismissed_(false) 
    52.         {
    53.         }
    54.         void Dismiss() const throw() 
    55.         {
    56.                 dismissed_ = true;
    57.         }
    58. };
    59. typedef const ScopeGuardImplBase& ScopeGuard;
    60. template <typename F>
    61. class ScopeGuardImpl0 : public ScopeGuardImplBase
    62. {
    63. public:
    64.         static ScopeGuardImpl0<F> MakeGuard(F fun)
    65.         {
    66.                 return ScopeGuardImpl0<F>(fun);
    67.         }
    68.         ~ScopeGuardImpl0() throw() 
    69.         {
    70.                 SafeExecute(*this);
    71.         }
    72.         void Execute() 
    73.         {
    74.                 fun_();
    75.         }
    76. protected:
    77.         ScopeGuardImpl0(F fun) : fun_(fun) 
    78.         {
    79.         }
    80.         F fun_;
    81. };
    82. template <typename F> 
    83. inline ScopeGuardImpl0<F> MakeGuard(F fun)
    84. {
    85.         return ScopeGuardImpl0<F>::MakeGuard(fun);
    86. }
    87. template <typename F, typename P1>
    88. class ScopeGuardImpl1 : public ScopeGuardImplBase
    89. {
    90. public:
    91.         static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
    92.         {
    93.                 return ScopeGuardImpl1<F, P1>(fun, p1);
    94.         }
    95.         ~ScopeGuardImpl1() throw() 
    96.         {
    97.                 SafeExecute(*this);
    98.         }
    99.         void Execute()
    100.         {
    101.                 fun_(p1_);
    102.         }
    103. protected:
    104.         ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) 
    105.         {
    106.         }
    107.         F fun_;
    108.         const P1 p1_;
    109. };
    110. template <typename F, typename P1> 
    111. inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
    112. {
    113.         return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
    114. }
    115. template <typename F, typename P1, typename P2>
    116. class ScopeGuardImpl2: public ScopeGuardImplBase
    117. {
    118. public:
    119.         static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
    120.         {
    121.                 return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
    122.         }
    123.         ~ScopeGuardImpl2() throw() 
    124.         {
    125.                 SafeExecute(*this);
    126.         }
    127.         void Execute()
    128.         {
    129.                 fun_(p1_, p2_);
    130.         }
    131. protected:
    132.         ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) 
    133.         {
    134.         }
    135.         F fun_;
    136.         const P1 p1_;
    137.         const P2 p2_;
    138. };
    139. template <typename F, typename P1, typename P2>
    140. inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
    141. {
    142.         return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
    143. }
    144. template <typename F, typename P1, typename P2, typename P3>
    145. class ScopeGuardImpl3 : public ScopeGuardImplBase
    146. {
    147. public:
    148.         static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
    149.         {
    150.                 return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
    151.         }
    152.         ~ScopeGuardImpl3() throw() 
    153.         {
    154.                 SafeExecute(*this);
    155.         }
    156.         void Execute()
    157.         {
    158.                 fun_(p1_, p2_, p3_);
    159.         }
    160. protected:
    161.         ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) 
    162.         {
    163.         }
    164.         F fun_;
    165.         const P1 p1_;
    166.         const P2 p2_;
    167.         const P3 p3_;
    168. };
    169. template <typename F, typename P1, typename P2, typename P3>
    170. inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
    171. {
    172.         return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
    173. }
    174. //************************************************************
    175. template <class Obj, typename MemFun>
    176. class ObjScopeGuardImpl0 : public ScopeGuardImplBase
    177. {
    178. public:
    179.         static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
    180.         {
    181.                 return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
    182.         }
    183.         ~ObjScopeGuardImpl0() throw() 
    184.         {
    185.                 SafeExecute(*this);
    186.         }
    187.         void Execute() 
    188.         {
    189.                 (obj_.*memFun_)();
    190.         }
    191. protected:
    192.         ObjScopeGuardImpl0(Obj& obj, MemFun memFun) 
    193.                 : obj_(obj), memFun_(memFun) {}
    194.         Obj& obj_;
    195.         MemFun memFun_;
    196. };
    197. template <class Obj, typename MemFun>
    198. inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
    199. {
    200.         return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
    201. }
    202. template <class Obj, typename MemFun, typename P1>
    203. class ObjScopeGuardImpl1 : public ScopeGuardImplBase
    204. {
    205. public:
    206.         static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
    207.         {
    208.                 return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
    209.         }
    210.         ~ObjScopeGuardImpl1() throw() 
    211.         {
    212.                 SafeExecute(*this);
    213.         }
    214.         void Execute() 
    215.         {
    216.                 (obj_.*memFun_)(p1_);
    217.         }
    218. protected:
    219.         ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) 
    220.                 : obj_(obj), memFun_(memFun), p1_(p1) {}
    221.         Obj& obj_;
    222.         MemFun memFun_;
    223.         const P1 p1_;
    224. };
    225. template <class Obj, typename MemFun, typename P1>
    226. inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
    227. {
    228.         return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
    229. }
    230. template <class Obj, typename MemFun, typename P1, typename P2>
    231. class ObjScopeGuardImpl2 : public ScopeGuardImplBase
    232. {
    233. public:
    234.         static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
    235.         {
    236.                 return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
    237.         }
    238.         ~ObjScopeGuardImpl2() throw() 
    239.         {
    240.                 SafeExecute(*this);
    241.         }
    242.         void Execute() 
    243.         {
    244.                 (obj_.*memFun_)(p1_, p2_);
    245.         }
    246. protected:
    247.         ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) 
    248.                 : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {}
    249.         Obj& obj_;
    250.         MemFun memFun_;
    251.         const P1 p1_;
    252.         const P2 p2_;
    253. };
    254. template <class Obj, typename MemFun, typename P1, typename P2>
    255. inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
    256. {
    257.         return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
    258. }
    259. #define CONCATENATE_DIRECT(s1, s2) s1##s2
    260. #define CONCATENATE(s1, s2) CONCATENATE_DIRECT(s1, s2)
    261. #define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
    262. #define ON_BLOCK_EXIT ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
    263. #define ON_BLOCK_EXIT_OBJ ScopeGuard ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
    264. //////////////////////////////////////////////////////////////////////////////////////////
    265. //      janitor
    266. struct ICmd_
    267. {
    268.         virtual void Dismiss() const throw() = 0;
    269.         virtual ~ICmd_() throw() {}
    270. };
    271. template<typename T>
    272. class CmdAdaptor : public ICmd_, protected T
    273. {
    274. public:
    275.         template<typename Fun>
    276.                 CmdAdaptor(Fun fun) : T(fun) {}
    277.         template<typename Fun, typename P1>
    278.                 CmdAdaptor(Fun fun, P1 p1) : T(fun, p1) {}
    279.         template<typename Fun, typename P1, typename P2>
    280.                 CmdAdaptor(Fun fun, P1 p1, P2 p2) : T(fun, p1, p2) {}
    281.         template<typename Fun, typename P1, typename P2, typename P3>
    282.                 CmdAdaptor(Fun fun, P1 p1, P2 p2, P3 p3) : T(fun, p1, p2, p3) {}
    283.         void Dismiss() const throw()
    284.         {
    285.                 T::Dismiss();
    286.         }
    287. };
    288. class Janitor
    289. {
    290. public:
    291.         Janitor() throw() {}
    292.         template <typename F>
    293.                 Janitor(F pFun) : spCmd_(
    294.                 new CmdAdaptor<ScopeGuardImpl0<F> >(pFun)) {}
    295.         template <typename F, typename P1>
    296.                 Janitor(F pFun, P1 p1) : spCmd_(
    297.                 new CmdAdaptor<ScopeGuardImpl1<F, P1> >(pFun, p1)) {}
    298.         template <typename F, typename P1, typename P2>
    299.                 Janitor(F pFun, P1 p1, P2 p2) : spCmd_(
    300.                 new CmdAdaptor<ScopeGuardImpl2<F, P1, P2> >(pFun, p1, p2)) {}
    301.         template <typename F, typename P1, typename P2, typename P3>
    302.                 Janitor(F pFun, P1 p1, P2 p2, P3 p3) : spCmd_(
    303.                 new CmdAdaptor<ScopeGuardImpl3<F, P1, P2, P3> >(pFun, p1, p2, p3)) {}
    304.         Janitor(const Janitor& other) throw() : spCmd_(other.spCmd_) {} //VC++, Comeau need it!
    305.         Janitor& operator =(const Janitor& other) throw()
    306.         {
    307.                 if (spCmd_.get())
    308.                         spCmd_->Dismiss();
    309.                 spCmd_ = other.spCmd_;
    310.                 return *this;
    311.         }
    312.         void Dismiss() const throw()
    313.         {
    314.                 spCmd_->Dismiss();
    315.         }
    316. protected:
    317.         mutable std::auto_ptr<ICmd_> spCmd_;
    318. };
    319. template<typename T>
    320. class ObjCmdAdaptor : public ICmd_, protected T
    321. {
    322. public:
    323.         template<typename Obj, typename MemFun>
    324.                 ObjCmdAdaptor(Obj& obj, MemFun memFun) : T(obj, memFun) {}
    325.         template<typename Obj, typename MemFun, typename P1>
    326.                 ObjCmdAdaptor(Obj& obj, MemFun memFun, P1 p1) : T(obj, memFun, p1) {}
    327.         template<typename Obj, typename MemFun, typename P1, typename P2>
    328.                 ObjCmdAdaptor(Obj& obj, MemFun memFun, P1 p1, P2 p2) : T(obj, memFun, p1, p2) {}
    329.         void Dismiss() const throw()
    330.         {
    331.                 T::Dismiss();
    332.         }
    333. };
    334. class ObjJanitor : protected Janitor
    335. {
    336. public:
    337.         using Janitor::Dismiss;
    338.         ObjJanitor() throw() {}
    339.         template <typename Obj, typename MemFun>
    340.                 ObjJanitor(Obj& obj, MemFun memFun)
    341.         {
    342.                 std::auto_ptr<ICmd_> spTmp(
    343.                         new ObjCmdAdaptor<ObjScopeGuardImpl0<Obj, MemFun> >(obj, memFun));
    344.                 spCmd_ = spTmp;
    345.         }
    346.         template <typename Obj, typename MemFun, typename P1>
    347.                 ObjJanitor(Obj& obj, MemFun memFun, P1 p1)
    348.         {
    349.                 std::auto_ptr<ICmd_> spTmp(
    350.                         new ObjCmdAdaptor<ObjScopeGuardImpl1<Obj, MemFun, P1> >(obj, memFun, p1));
    351.                 spCmd_ = spTmp;
    352.         }
    353.         template <typename Obj, typename MemFun, typename P1, typename P2>
    354.                 ObjJanitor(Obj& obj, MemFun memFun, P1 p1, P2 p2)
    355.         {
    356.                 std::auto_ptr<ICmd_> spTmp(
    357.                         new ObjCmdAdaptor<ObjScopeGuardImpl2<Obj, MemFun, P1, P2> >(obj, memFun, p1, p2));
    358.                 spCmd_ = spTmp;
    359.         }
    360. };
    使用范例
    1. #include "stdafx.h"
    2. #include <iostream>
    3. #include <string>
    4. using namespace std;
    5. #include "janitor.hpp"
    6. class class1
    7. {
    8. public:
    9.     class1()
    10.     {
    11.     }
    12.     ~class1()
    13.     {
    14.     }
    15. public:
    16.     void test()
    17.     {
    18.         ObjJanitor ja(*this,&class1::testJanitor);
    19.     }
    20.     void testJanitor()
    21.     {
    22.         cout << "hello world" << endl;
    23.     }
    24. };
    25. int _tmain(int argc, _TCHAR* argv[])
    26. {
    27.     class1 c;
    28.     c.test();
    29.     return 0;
    30. }
    二.controlled_module 可被关闭的线程类
     该类原型来自于一个叫“阿修罗”的原始类
    1. // controlled_module.hpp : 可主动关闭的boost线程类
    2. //
    3. #pragma once
    4. #include   <boost/utility.hpp>   
    5. #include   <boost/thread/condition.hpp>   
    6. #include   <boost/thread/mutex.hpp>
    7. #include <boost/thread/thread.hpp>
    8. #include <boost/bind.hpp>
    9. #include "janitor.hpp"
    10. class   controlled_module_implement   :   boost::noncopyable   {   
    11.   public:   
    12.   controlled_module_implement()   :active_(false),command_exit_(false){}   
    13.   boost::condition   module_is_exit;   
    14.   boost::mutex   monitor;   
    15.   void   active(bool   ac)   
    16.   {boost::mutex::scoped_lock   lk(monitor);   if(!(active_=ac))module_is_exit.notify_all();else   command_exit_=false;}   
    17.   bool   command_exit(){boost::mutex::scoped_lock   lk(monitor);   return   command_exit_;}   
    18.   bool   active_,command_exit_;   
    19.     
    20.   };
    21.   class   controlled_module   :   boost::noncopyable   {   
    22.   public:   
    23.   virtual   void   run()
    24.   {
    25.       ObjJanitor   janitor(*impl_,&controlled_module_implement::active,false);   
    26.     impl_->active(true);   
    27.     {   
    28.         ObjJanitor   janitor(*this,&controlled_module::release);   
    29.         if(this->initialize())   
    30.         {   
    31.             m_live = true;
    32.             SetEvent(m_event_init);
    33.             while(!impl_->command_exit()   &&  this->islive() &&  this->work())
    34.             {
    35.             }
    36.         }
    37.         else
    38.         {
    39.             m_live = false;
    40.             SetEvent(m_event_init);
    41.         }
    42.     }  
    43.   }
    44.   bool   exit(unsigned   long   sec=0)
    45.   {
    46.   boost::mutex::scoped_lock   lk(impl_->monitor);   
    47.   impl_->command_exit_   =   true;   
    48.   while(impl_->active_)   
    49.   {   
    50.   if(sec)   
    51.   {   
    52.   boost::xtime   xt;   
    53.   boost::xtime_get(&xt,   boost::TIME_UTC);   
    54.   xt.sec   +=   sec;   
    55.   if(!impl_->module_is_exit.timed_wait(lk,xt))   
    56.   return   false;   
    57.   }   
    58.   else   
    59.   impl_->module_is_exit.wait(lk);   
    60.   }   
    61.   return   true;   
    62.   }
    63.   protected:   
    64.   controlled_module()
    65.   :impl_(new   controlled_module_implement)   
    66.   ,m_live(false)
    67.   ,m_event_init(0)
    68.   ,m_sleeptime(10)
    69.   {     
    70.   }   
    71.   virtual   ~controlled_module()
    72.   {
    73.       if(m_live)
    74.           stop();
    75.       delete   impl_;   
    76.   }
    77.   private:    
    78.       virtual   bool   initialize(){return true;} 
    79.       virtual   void   release(){}
    80.   protected:
    81.       virtual   bool   work()
    82.       {
    83.         Sleep(this->m_sleeptime);
    84.         return true;
    85.       }
    86.       int m_sleeptime;
    87.   private:   
    88.     bool m_live;
    89.     void * m_event_init;
    90.  controlled_module_implement*   impl_;   
    91.   public:
    92.     bool start()
    93.     {
    94.         m_event_init = CreateEvent(NULL,FALSE,FALSE,"");
    95.         boost::thread thd(boost::bind(&controlled_module::run,this));
    96.         ::WaitForSingleObject(m_event_init,INFINITE);
    97.         CloseHandle(m_event_init);
    98.         m_event_init = 0;
    99.         return m_live;
    100.     }
    101.     void stop()
    102.     {
    103.         m_live = false;
    104.         exit(1);
    105.     }
    106.     bool islive(){return m_live;}
    107.     void die()
    108.     {
    109.       m_live = false;
    110.         SetEvent(m_event_init);
    111.     }
    112.     void setsleeptime(int n)
    113.     {
    114.       m_sleeptime = n;
    115.     }
    116.   };
    117.     
      virtual   bool   initialize();   初始化
      virtual   void   release();   释放
      virtual   bool   work();   工作函数
      如果我们要创建一个可被关闭的线程,可以如下步骤:
      1)创建一个controlled_module 继承类
      2)实现3个虚拟函数
      3)用start(),stop()启动和停止线程
    范例:
     
    1. //controlled_module demo
    2. #include "controlled_module.hpp"
    3. class thd: public controlled_module
    4. {
    5. public:
    6.     virtual bool initialize()
    7.     {
    8.         cout << "thd init" << endl;
    9.         return true;
    10.     }
    11.     virtual void release()
    12.     {
    13.         cout << "thd release" << endl;
    14.     }
    15.     virtual bool work()
    16.     {
    17.         //your work........
    18.         return controlled_module::work();
    19.     }
    20. };
    21. int _tmain(int argc, _TCHAR* argv[])
    22. {
    23.     thd t;
    24.     t.start();
    25.     char buf[10];
    26.     gets_s(buf,sizeof buf);
    27.     t.stop();
    28.     return 0;
    29. }
    thd线程在启动以后,将循环执行work()函数,直到线程退出
  • 相关阅读:
    Sql Server 邮件日志 操作 IT
    导出Excel IT
    Sqlserver 2005 修改数据库默认排序 IT
    SqlServer 备份数据库语法 IT
    HDFS常用shell命令
    改写UMFPACK算例中的压缩方式(动态)
    umFPACK使用调用(一)
    改写UMFPACK算例中的压缩方式(静态)
    利用C/C++实现从文件读入到子程序中调用返回结果
    改写UMFPACK算例中的压缩方式
  • 原文地址:https://www.cnblogs.com/lvdongjie/p/4447785.html
Copyright © 2011-2022 走看看