將Linux的訊號量sem_t封裝成事件物件
阿新 • • 發佈:2019-02-09
將訊號量sem_t相關的一組API封裝成Win32平臺上的事件物件類之後,在Linux平臺上就可以像使用事件物件那樣,方便地進行執行緒同步了。
class CEventImpl
{
protected:
/*
建立匿名訊號量
`bAutoReset true 人工重置
false 自動重置
*/
CEventImpl(bool manualReset);
/*
登出訊號量
*/
~CEventImpl();
/*
將當前事件物件設定為有訊號狀態
若自動重置,則等待該事件物件的所有執行緒只有一個可被排程
若人工重置,則等待該事件物件的所有執行緒變為可被排程
*/
void SetImpl();
/*
以當前事件物件,阻塞執行緒,將其永遠掛起
直到事件物件被設定為有訊號狀態
*/
bool WaitImpl();
/*
以當前事件物件,阻塞執行緒,將其掛起指定時間間隔
之後執行緒自動恢復可排程
*/
bool WaitImpl(long milliseconds);
/*
將當前事件物件設定為無訊號狀態
*/
void ResetImpl();
private:
bool m_manual;
sem_t m_event;
};
inline void CEventImpl::SetImpl()
{
int ret = sem_post(&m_event);
if ( 0 != ret )
{
cout<<"cannot signal event"<<endl;
}
}
inline void CEventImpl::ResetImpl()
{
int sval = 0;
do
{
sem_trywait(&m_event);
sem_getvalue(&m_event, &sval);
} while(sval > 0);
}
CEventImpl::CEventImpl(bool manualReset): m_manual(manualReset)
{
unsigned int nValue = 0; //初始化為無訊號
int ret = sem_init(&m_event, 0, nValue);
if ( 0 != ret )
{
cout<<"sem_init failed"<<endl;
}
}
CEventImpl::~CEventImpl()
{
sem_destroy(&m_event);
}
bool CEventImpl::WaitImpl()
{
int ret = sem_wait(&m_event);
if ( 0 != ret )
{
cout<<"CEventImpl::WaitImpl sem_wait failed"<<endl;
}
if ( m_manual )
{
sem_post(&m_event);
}
return true;
}
bool CEventImpl::WaitImpl(long milliseconds)
{
if ( 0 == milliseconds )
{
int ret = sem_trywait(&m_event);
if ( 0 == ret )
{
if ( m_manual )
{
sem_post(&m_event);
}
}
}
else
{
int roopMax = milliseconds/10;
do
{
usleep(10*1000);
int ret = sem_trywait(&m_event);
if ( 0 == ret )
{
if ( m_manual )
{
sem_post(&m_event);
}
break;
}
roopMax--;
} while( roopMax > 0 );
}
return true;
}
類CEventImpl