網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
C++實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的事件(Event)的示例代碼_C 語(yǔ)言
作者:程序員~彭國(guó)慶 ? 更新時(shí)間: 2022-12-13 編程語(yǔ)言一、前言
利用 WaitForSingleObject 檢查內(nèi)核對(duì)象的狀態(tài)來(lái)進(jìn)行實(shí)現(xiàn)。后來(lái)隨著需要開(kā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)闆](méi)有裸露的指針資源,移動(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è)試, 鍵盤(pán)輸入字符 ‘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’ 回車(chē)后,TestEventFunc1或者TestEventFunc2線程函數(shù)中的循環(huán)體就會(huì)被執(zhí)行一次,每個(gè)循環(huán)體執(zhí)行兩次后等待 5 秒線程就退出,再輸入‘q’ 退出程序。實(shí)際運(yùn)行結(jié)果如下:
符合預(yù)期。
原文鏈接:https://blog.csdn.net/PX1525813502/article/details/127825325
相關(guān)推薦
- 2022-11-29 redis命令行操作庫(kù)、鍵、和五大數(shù)據(jù)類型詳解
- 2023-01-01 C++?Boost?Flyweight庫(kù)使用介紹_C 語(yǔ)言
- 2022-12-16 C++?Boost?EnableIf函數(shù)使用介紹_C 語(yǔ)言
- 2022-07-07 Python筆記之a(chǎn)?=?[0]*x格式的含義及說(shuō)明_python
- 2023-03-23 python跳出雙層循環(huán)的方法_python
- 2022-07-13 常用類之BigDecimal、Date、Calender、SimpleDateFormat及Syst
- 2023-06-21 Android崩潰日志收集和保存解析_Android
- 2022-11-05 ios開(kāi)發(fā)?try-catch引起的野指針問(wèn)題排查_(kāi)IOS
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支