标准C++与线程

标准C++和标准库中没有对线程的封装,程序员们不得不使用OS提供的API来处理线程,OS级别的API通常基于C,能用,但并不方便。最近看到论坛上有人问,顺便和同事讨论这个问题,如何使用标准C++封装线程的操作,目的就是simple and easy to use。想想自己似乎多年前(已经结蜘蛛网了)写过这方面的代码,找了找,还真找到了,是Windows平台的,整理一下,与大家分享。

  1. // 抽象类,作为线程类的基类,定义了几个接口  
  2.   
  3. // abstract class to provide interface.  
  4. //   
  5. class GeneralThread  
  6. {  
  7. public:  
  8.  virtual ~GeneralThread() {}  
  9.   
  10. public:  
  11.  // create thread and run with specified priority  
  12.  virtual void Run( long priority = THREAD_PRIORITY_BELOW_NORMAL ) = 0;  
  13.  // wait thread running till timeout  
  14.  virtual unsigned long Join( unsigned long ms = INFINITE ) = 0;  
  15.   
  16.  virtual unsigned long GetExitCode() const = 0;  
  17.   
  18.  // end thread ingore thread status.  
  19.  virtual void End() {}  
  20. };  
  21.   
  22. typedef GeneralThread     GThread;  
  23. typedef GThread *      CThreadPtr;  
  24.   
  25.    
  26.   
  27. // 一个子类,实现了基类的接口,并且定义了一个新的接口来运行真正的线程函数  
  28.   
  29. // 因此,可以从这个类继续派生新的子类,实现自定义的线程函数。  
  30.   
  31. // a derived calss from GeneralThread  
  32. //   
  33. class SomeThread : public GeneralThread  
  34. {  
  35. public:  
  36.  SomeThread() : m_hThread(0)  
  37.  {  
  38.  }  
  39.   
  40.  ~SomeThread()  
  41.  {  
  42.   //Join( INFINITE );  
  43.   if( m_hThread )  
  44.   {  
  45.    CloseHandle( m_hThread );  
  46.    m_hThread = NULL;  
  47.   }  
  48.  }  
  49. public:  
  50.  // new interface to implement thread actions  
  51.  virtual unsigned long ThreadProc() = 0;  
  52.   
  53. public:  
  54.  virtual void Run( long priority )  
  55.  {  
  56.   m_hThread = CreateThread( NULL, 0, &SomeThread::ThreadProc, this, CREATE_SUSPENDED, NULL );  
  57.   
  58.   if( m_hThread )  
  59.   {  
  60.    SetThreadPriority( m_hThread, priority );  
  61.    ResumeThread( m_hThread );  
  62.   }  
  63.   else  
  64.   {  
  65.    DWORD dw = GetLastError();  
  66.    UNREFERENCED_PARAMETER( dw );  
  67.   }  
  68.  }  
  69.   
  70.  virtual unsigned long Join( unsigned long ms )  
  71.  {  
  72.   unsigned long ul = WAIT_OBJECT_0;  
  73.   
  74.   if( m_hThread )  
  75.   {  
  76.    ul = WaitForSingleObject( m_hThread, ms );  
  77.   
  78.    switch( ul )  
  79.    {  
  80.    case WAIT_OBJECT_0:  
  81.     //GetExitCodeThread( m_hThread, &m_exitCode );  
  82.     break;  
  83.   
  84.    case WAIT_TIMEOUT:  
  85.     break;  
  86.   
  87.    case WAIT_FAILED:  
  88.     ul = ul;  
  89.     break;  
  90.    }  
  91.   }  
  92.   
  93.   return ul;  
  94.  }  
  95.   
  96.  virtual unsigned long GetExitCode() const  
  97.  {  
  98.   DWORD exitCode = 0;  
  99.   GetExitCodeThread( m_hThread, &exitCode );  
  100.   return exitCode;  
  101.  }  
  102.   
  103.  virtual void End()  
  104.  {  
  105.   TerminateThread( m_hThread, 0xabcd );  
  106.  }  
  107.   
  108. private:  
  109.  static unsigned long WINAPI ThreadProc( LPVOID lpParameter )  
  110.  {  
  111.   SomeThread *p = static_cast< SomeThread * >( lpParameter );  
  112.   return p->ThreadProc();  
  113.  }  
  114.   
  115. private:  
  116.  HANDLE m_hThread;  
  117. };  
  118.   
  119.    
  120.   
  121. // 虽然可以从SomeThread 派生子类,但是如果有多个线程,并且每个线程的线程函数不一样的话,  
  122.   
  123. // 那么需要实现多个子类,并不是很方便。考虑到标准C++推荐使用模板和函数对象,因此派生了一个  
  124.   
  125. // 子类,重新实现了父类中的虚函数,转发成对函数对象的访问。  
  126.   
  127. //  
  128. // if you want to implement your thread, you have to derive a class from SomeThread and also implement your thread procedure.  
  129. // sometimes you will feel boring.  
  130. // so here we implement a template class to simplify usage.  
  131. // thus you don't need to code your derived class, instead just provide your function object.  
  132. //   
  133. templatetypename F >  
  134. class ConcreteThread : public SomeThread  
  135. {  
  136. public:  
  137.  ConcreteThread( const F &f ) : m_f(f)  
  138.  {  
  139.  }  
  140.   
  141. private:  
  142.  unsigned long ThreadProc()  
  143.  {  
  144.   return m_f();  
  145.  }  
  146.   
  147. private:  
  148.  F m_f;  
  149. };  
  150.   
  151. templatetypename F >  
  152. CThreadPtr MakeThread( F &f )  
  153. {  
  154.  return new ConcreteThread< F >( f );  
  155. }  
  156.   
  157.    
  158.   
  159. // 这个类提供了另一种形式的封装。  
  160.   
  161. // this class is just for simple usage in  stack scope.  
  162. //   
  163. class Thread  
  164. {  
  165. public:  
  166.  templatetypename F >  
  167.   Thread( F &f ) : m_pThread( MakeThread(f) )  
  168.  {  
  169.   m_pThread->Run();  
  170.  }  
  171.   
  172.  ~Thread()  
  173.  {  
  174.   delete m_pThread;  
  175.  }  
  176.   
  177. public:  
  178.  unsigned long Join()  
  179.  {  
  180.   return m_pThread->Join();  
  181.  }  
  182.   
  183.  unsigned long ExitCode()  
  184.  {  
  185.   return m_pThread->GetExitCode();  
  186.  }  
  187.   
  188. private:  
  189.  CThreadPtr m_pThread;  
  190. };  

代码不长,而且加了些注释,不难理解。下面是测试用的代码

  1. int sum( int end )  
  2. {  
  3.  int sum = 0;  
  4.  forint i = 0 ; i < end ; i++ )  
  5.  {  
  6.   sum += i;  
  7.  }  
  8.  return sum;  
  9. }  
  10.   
  11. void TestThread()  
  12. {  
  13.  // test Thread class  
  14.  Thread t( std::bind( sum, 10000 ) ), t2( std::bind( sum, 20000 ) );  
  15.  t.Join();   
  16. t2.Join();  
  17.  std::cout << "sum1 = " << t.ExitCode() << "; sum2 = " << t2.ExitCode() << std::endl;  
  18.   
  19.  // test ConcreteThread  
  20.  CThreadPtr p = MakeThread( std::bind( sum, 50000 ) );  
  21.  p->Run();  
  22.  p->Join();  
  23.   
  24.  std::cout << "sum3 = " << p->GetExitCode() << std::endl;  
  25.  //delete p;  
  26.   
  27.  std::auto_ptr< GeneralThread > p2( MakeThread( std::bind( sum, 50001 ) ) );  
  28.  p->Run(); p->Join();  
  29.  std::cout <<"sum4 = " << p->GetExitCode() << std::endl;  
  30. }  

测试代码很简短,使用了标准C++的std::bind把sum函数包装成函数对象,然后在单独的线程中运行。

一般而言,使用C++封装系统API以方便使用,通常难度不大,代码也不会太长。这是一个典型的例子。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值