C++实现一个简易版的事件(Event)的示例代码
程序员~彭国庆 人气:0一、前言
利用 WaitForSingleObject 检查内核对象的状态来进行实现。后来随着需要开发跨平台的程序后这种方式就不能使用了, 毕竟这是 windows 专属。 POCO 库在 windows之外的系统选择利用 pthread 线程库库来实现 Event, pthread 毕竟不在C++标准库里面,假设要使用的话需要单独配置。所以本文就利用 C++11之后的标准库内容来实现一个事件类, 方便使用。
本文代码地址:https://github.com/pengguoqing/samples_code
二、实现
2.1 需要具备的功能
①支持多线程
②可以等待一定时间
2.2 代码实现
一共提供四个对外接口, 分别如下:
//设置事件有信号 inline void SetEvent() const; //重置事件为无信号 inline void ResetEvent() const; //持续等待直到事件有信号, 如果是 Auto 模式则必须等待到该线程能拿到状态 inline void Wait() const; //等待事件一定时间, 时间范围内事件有信号则返回 true,否则返回 false template <typename Rep, typename Period> inline bool tryWait(const std::chrono::duration<Rep, Period>& duratio) const;
类内部再对具体的实现进行一下封装
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 对 EventImpl 资源进行管理:
const std::shared_ptr<EventImpl> m_event;
因为没有裸露的指针资源,移动和拷贝函数就直接全部使用编译器默认的
explicit CXEvent(Mode mode = Mode::Auto, bool initstate = false); ~CXEvent() = default;
三、测试
测试用一个事件实例来实现两个线程的同步测试, 键盘输入字符 ‘s’ 触发一次事件, 每个线程 Wait() 两次事件后,再测试一下 tryWait() 时间。代码如下:
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"; }
期望结果是每输入一次 ‘s’ 回车后,TestEventFunc1或者TestEventFunc2线程函数中的循环体就会被执行一次,每个循环体执行两次后等待 5 秒线程就退出,再输入‘q’ 退出程序。实际运行结果如下:
符合预期。
加载全部内容