1. 程式人生 > >Linux平臺用C++實現訊號量,同步執行緒

Linux平臺用C++實現訊號量,同步執行緒

    使用Linux平臺上現有的訊號量sem_t相關的一組API,可以方便地進行執行緒同步。現在用pthread_mutex_t和pthread_cond_t相關的一組API實現訊號量機制。這組API包括:pthread_mutex_init,pthread_cond_init,pthread_mutex_lock,pthread_cond_signal,pthread_mutex_unlock,pthread_cond_wait,pthread_cond_timedwait,pthread_cond_destroy和pthread_mutex_destroy,可以在http://www.9linux.com

找到各API的說明。下邊,是封裝的訊號量類,以及測試程式碼。使用VS2005編輯,在虛擬機器 Fedora 13中編譯,測試通過。

MySemaphore.h

  1. #ifndef Semaphore_Header
  2. #define Semaphore_Header
  3. #include <iostream>
  4. #include <pthread.h>
  5. #include <errno.h>
  6. #include <assert.h>
  7. usingnamespace std;  
  8. //------------------------------------------------------------------------
  9. class CSemaphoreImpl  
  10. {  
  11. protected:  
  12.     CSemaphoreImpl(int n, int max);       
  13.     ~CSemaphoreImpl();  
  14.     void SetImpl();  
  15.     void WaitImpl();  
  16.     bool WaitImpl(long lMilliseconds);  
  17. private:  
  18.     volatileint    m_n;  
  19.     int             m_max;  
  20.     pthread_mutex_t m_mutex;  
  21.     pthread_cond_t  m_cond;  
  22. };  
  23. inlinevoid CSemaphoreImpl::SetImpl()  
  24. {  
  25.     if (pthread_mutex_lock(&m_mutex))     
  26.         cout<<"cannot signal semaphore (lock)"<<endl;  
  27.     if (m_n < m_max)  
  28.     {  
  29.         ++m_n;  
  30.     }  
  31.     else
  32.     {  
  33.         pthread_mutex_unlock(&m_mutex);  
  34.         cout<<"cannot signal semaphore: count would exceed maximum"<<" m_n = "<<m_n<<"m_max = "<<m_max<<endl;  
  35.     }  
  36.     //重新開始等待m_cond的執行緒,可被排程
  37.     if (pthread_cond_signal(&m_cond))  
  38.     {  
  39.         pthread_mutex_unlock(&m_mutex);  
  40.         cout<<"cannot signal semaphore"<<endl;  
  41.     }  
  42.     pthread_mutex_unlock(&m_mutex);  
  43. }  
  44. //------------------------------------------------------------------------
  45. /* 
  46.  訊號量同步機制 
  47.  訊號量提供一個計數值,可以進行原子操作。V 將計數值加1,使得 
  48.  等待該訊號量的執行緒可以被呼叫(呼叫Set()),P 將計數值減1,使 
  49.  當前執行緒被掛起,進行睡眠(呼叫Wait())。 
  50.  當訊號量的計數值被初始化為0時,呼叫P操作,將掛起當前執行緒。 
  51.  當訊號量被啟用,即呼叫V操作後,被掛起的執行緒就有機會被重新排程了。 
  52. */
  53. class CMySemaphore: private CSemaphoreImpl  
  54. {  
  55. public:  
  56.     /* 
  57.      建立一個訊號量,訊號量計數值當前值為引數n,最大值為max。 
  58.      如果只有n,則n必須大於0;如果同時有n和max,則n必須不小 
  59.      於0,且不大於max 
  60.     */
  61.     CMySemaphore(int n);  
  62.     CMySemaphore(int n, int max);  
  63.     /* 
  64.      銷燬一個訊號量 
  65.     */
  66.     ~CMySemaphore();  
  67.     /* 
  68.      對訊號量計數值做加1動作,訊號量變為有訊號狀態,使得 
  69.      另一個等待該訊號量的執行緒可以被排程 
  70.     */
  71.     void Set();  
  72.     /* 
  73.      對訊號量計數值做減1動作,訊號量變為無訊號狀態。若 
  74.      計數值變得大於0時,訊號量才會變為有訊號狀態。 
  75.     */
  76.     void Wait();  
  77.     /* 
  78.      在給定的時間間隔裡等待訊號量變為有訊號狀態,若成功, 
  79.      則將計數值減1,否則將發生超時。 
  80.     */
  81.     void Wait(long lMilliseconds);  
  82.     /* 
  83.      在給定的時間間隔裡等待訊號量變為有訊號狀態,若成功, 
  84.      則將計數值減1,返回true;否則返回false。 
  85.     */
  86.     bool TryWait(long lMilliseconds);  
  87. private:  
  88.     CMySemaphore();  
  89.     CMySemaphore(const CMySemaphore&);  
  90.     CMySemaphore& operator = (const CMySemaphore&);  
  91. };  
  92. inlinevoid CMySemaphore::Set()  
  93. {  
  94.     SetImpl();  
  95. }  
  96. inlinevoid CMySemaphore::Wait()  
  97. {  
  98.     WaitImpl();  
  99. }  
  100. inlinevoid CMySemaphore::Wait(long lMilliseconds)  
  101. {  
  102.     if (!WaitImpl(lMilliseconds))  
  103.         cout<<"time out"<<endl;  
  104. }  
  105. inlinebool CMySemaphore::TryWait(long lMilliseconds)  
  106. {  
  107.     return WaitImpl(lMilliseconds);  
  108. }  
  109. #endif

MySemaphore.cpp
  1. #include "MySemaphore.h"
  2. #include <sys/time.h>
  3. CSemaphoreImpl::CSemaphoreImpl(int n, int max): m_n(n), m_max(max)  
  4. {  
  5.     assert (n >= 0 && max > 0 && n <= max);  
  6.     if (pthread_mutex_init(&m_mutex, NULL))  
  7.         cout<<"cannot create semaphore (mutex)"<<endl;  
  8.     if (pthread_cond_init(&m_cond, NULL))