C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的示例代碼
一、前言
利用 WaitForSingleObject 檢查內(nèi)核對(duì)象的狀態(tài)來(lái)進(jìn)行實(shí)現(xiàn)。后來(lái)隨著需要開發(fā)跨平臺(tái)的程序后這種方式就不能使用了, 畢竟這是 windows 專屬。 POCO 庫(kù)在 windows之外的系統(tǒng)選擇利用 pthread 線程庫(kù)庫(kù)來(lái)實(shí)現(xiàn) Event, pthread 畢竟不在C++標(biāo)準(zhǔn)庫(kù)里面,假設(shè)要使用的話需要單獨(dú)配置。所以本文就利用 C++11之后的標(biāo)準(zhǔn)庫(kù)內(nèi)容來(lái)實(shí)現(xiàn)一個(gè)事件類, 方便使用。
本文代碼地址:https://github.com/pengguoqing/samples_code
二、實(shí)現(xiàn)
2.1 需要具備的功能
①支持多線程
②可以等待一定時(shí)間
2.2 代碼實(shí)現(xiàn)
一共提供四個(gè)對(duì)外接口, 分別如下:
//設(shè)置事件有信號(hào) inline void SetEvent() const; //重置事件為無(wú)信號(hào) inline void ResetEvent() const; //持續(xù)等待直到事件有信號(hào), 如果是 Auto 模式則必須等待到該線程能拿到狀態(tài) inline void Wait() const; //等待事件一定時(shí)間, 時(shí)間范圍內(nèi)事件有信號(hào)則返回 true,否則返回 false template <typename Rep, typename Period> inline bool tryWait(const std::chrono::duration<Rep, Period>& duratio) const;
類內(nèi)部再對(duì)具體的實(shí)現(xiàn)進(jìn)行一下封裝
struct EventImpl { explicit EventImpl(Mode mode, bool initState); ~EventImpl() = default; inline void Set(); inline void Reset(); inline void Wait(); template <typename Rep, typename Period> inline bool Wait_for(const std::chrono::duration<Rep, Period>& duration); std::mutex m_mutex; std::condition_variable m_condi; bool m_signal; const Mode m_mode; };
使用 unique_ptr 對(duì) EventImpl 資源進(jìn)行管理:
const std::shared_ptr<EventImpl> m_event;
因?yàn)闆]有裸露的指針資源,移動(dòng)和拷貝函數(shù)就直接全部使用編譯器默認(rèn)的
explicit CXEvent(Mode mode = Mode::Auto, bool initstate = false); ~CXEvent() = default;
三、測(cè)試
測(cè)試用一個(gè)事件實(shí)例來(lái)實(shí)現(xiàn)兩個(gè)線程的同步測(cè)試, 鍵盤輸入字符 ‘s’ 觸發(fā)一次事件, 每個(gè)線程 Wait() 兩次事件后,再測(cè)試一下 tryWait() 時(shí)間。代碼如下:
using namespace std; static CXEvent kEvent; static constexpr int testCnt = 3; TestEventFunc1(const CXEvent& refEvent) { for (int i=0; i< testCnt; i++) { if (i == testCnt-1) { auto begin = chrono::high_resolution_clock::now(); kEvent.tryWait(5000ms); auto end = chrono::high_resolution_clock::now(); auto duration = chrono::duration_cast<chrono::microseconds>(end - begin); cout << "TestEventFunc1"<<"tryWait time:"<< duration.count() << endl; } else { kEvent.Wait(); cout << "TestEventFunc1 Wait" << endl; } } } TestEventFunc2(const CXEvent& refEvent) { for (int i=0; i<testCnt; i++) { if (i == testCnt-1) { auto begin = chrono::high_resolution_clock::now(); kEvent.tryWait(5000ms); auto end = chrono::high_resolution_clock::now(); auto duration = chrono::duration_cast<chrono::microseconds>(end - begin); cout << "TestEventFunc2" << "tryWait time:"<< duration.count()<< endl; } else { kEvent.Wait(); cout << "TestEventFunc2 Wait" << endl; } } } int main() { CXEvent refEvent1(kEvent); CXEvent refEvent2(kEvent); std::thread testTh1(TestEventFunc1, refEvent1); std::thread testTh2(TestEventFunc2, refEvent2); int cinCnt{0}; char inputCmd {'R'}; cin.get(inputCmd); while ('q'!=inputCmd && cinCnt<testCnt*2) { if ('s' == inputCmd) { kEvent.SetEvent(); cinCnt++; } cin.get(inputCmd); } if (testTh1.joinable()) { testTh1.join(); } if (testTh2.joinable()) { testTh2.join(); } std::cout << "test set event and wait_for event\n"; }
期望結(jié)果是每輸入一次 ‘s’ 回車后,TestEventFunc1或者TestEventFunc2線程函數(shù)中的循環(huán)體就會(huì)被執(zhí)行一次,每個(gè)循環(huán)體執(zhí)行兩次后等待 5 秒線程就退出,再輸入‘q’ 退出程序。實(shí)際運(yùn)行結(jié)果如下:
符合預(yù)期。
到此這篇關(guān)于C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的示例代碼的文章就介紹到這了,更多相關(guān)C++事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++內(nèi)存管理之簡(jiǎn)易內(nèi)存池的實(shí)現(xiàn)
大家好,本篇文章主要講的是C++內(nèi)存管理之簡(jiǎn)易內(nèi)存池的實(shí)現(xiàn),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2021-12-12一篇文章教你如何用C語(yǔ)言實(shí)現(xiàn)strcpy和strlen
這篇文章主要為大家介紹了C語(yǔ)言實(shí)現(xiàn)strcpy和strlen的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-01-01