1# 事件处理系统 2## 概述 3事件处理系统。c_utils提供基于Reactor模式,以epoll为后台多路复用机制,通过文件描述符fd实现对各I/O设备的基于事件的异步处理机制。 4 5开发者通过构造事件描述对象(`IOEventHandler`),指定由Fd指定的被监听I/O设备(不支持普通文件)、具体监听的事件类型以及捕获目标事件后的响应行为(回调函数)。 6 7随后开发者需要构造事件处理系统的中心响应器对象(`IOEventReactor`),该中心响应器对象将根据对监听事件以及响应行为的描述,捕获目标事件并对事件进行响应。 8 9## 相关原理 10 11### UML类图 12```mermaid 13classDiagram 14direction LR 15 16class EventHandler{ 17 <<Abstact>> 18 + Start() 19 + Stop() 20 + Close() 21} 22 23class IOEventHandler{ 24 - IOEventHandler* prev 25 - IOEventHandler* next 26 - IOEventReactor* loop 27 - IOEventCallback cb 28 - uint32_t events 29 - int fd 30 + Start() override 31 + Stop() override 32} 33 34class TimerEventHandler{ 35 - uint32_t interval 36 + Start() override 37 + Stop() override 38 + Close() override 39} 40 41class FdEvents{ 42 <<struct>> 43 IOEventHandler* head 44 uint32_t emask 45 uint8_t flags 46} 47 48class EventReactor{ 49 <<Abstact>> 50 + Run() 51 + CleanUp() 52 + AddHandler() 53 + RemoveHandler() 54} 55 56class IOEventReactor{ 57 - struct FdEventsHead 58 - struct FdEvents 59 - std::vector~FdEventsHead~ io_handlers 60 - EventDemultiplexer* backend 61 + Run() override 62 + CleanUp() override 63 + AddHandler() override 64 + RemoveHandler() override 65 + SetDemultiplexer(): 66} 67 68class EventDemultiplexer{ 69 <<Abstact>> 70 + Poll() 71} 72 73class IOEventEpoll{ 74 - int epfd 75 + Poll() override 76 + ModifyEvents() 77 + CleanUp() 78} 79 80 81IOEventHandler ..|> EventHandler 82TimerEventHandler --|> IOEventHandler 83IOEventReactor ..|> EventReactor 84FdEvents --* IOEventReactor 85IOEventHandler --> FdEvents 86IOEventHandler ..> IOEventReactor 87EventEpoll ..|> EventDemultiplexer 88EventEpoll --o IOEventReactor 89``` 90### IOEventReactor内数据结构 91 92 93### 94 95## 涉及功能 96### OHOS::Utils::Events 97#### 描述 98```cpp 99namespace OHOS::Utils::Events; 100``` 101命名空间`Events`包含了c_utils中事件处理器功能中各兴趣事件的事件类型。 102 103`#include <io_event_common.h>` 104 105同时`io_event_common.h`头文件中定义了表示事件类型的C++类型`EventId`、表示响应行为的C++类型`EventCallback`(即`std::function<void()>`)。 106#### 属性 107 108| | 名称 | 109| -------------- | -------------- | 110| constexpr EventId | **EVENT_CLOSE** <br>关闭事件。表明当前事件监听“关闭”事件。 | 111| constexpr EventId | **EVENT_ERROR** <br>错误事件。表明当前事件监听“错误”事件。 | 112| constexpr EventId | **EVENT_INVALID** <br>非法事件。表明当前事件类型设置非法。 | 113| constexpr EventId | **EVENT_NONE** <br>空事件。表明当前事件不监听任何事件类型。 | 114| constexpr EventId | **EVENT_READ** <br>可读事件。表明当前事件监听“可读”事件。 | 115| constexpr EventId | **EVENT_WRITE** <br>可写事件。表明当前事件监听“可写”事件。 | 116 117### OHOS::Utils::IOEventHandler 118#### 描述 119```cpp 120class OHOS::Utils::IOEventHandler; 121``` 122事件描述类。其描述了兴趣IO事件的具体事件类型以及具体响应行为。 123当事件系统捕获到响应类型的事件时,将按照该事件描述类对象中定义的响应行为进行响应。 124 125`#include <io_event_handler.h>` 126 127#### 公共成员函数 128 129| 返回类型 | 名称 | 130| -------------- | -------------- | 131| | **IOEventHandler**()<br>默认构造函数。其Fd为-1。 | 132| | **IOEventHandler**(const IOEventHandler && ) =delete | 133| | **IOEventHandler**(const IOEventHandler & ) =delete | 134| | **IOEventHandler**(int fd, EventId events =Events::EVENT_NONE, const EventCallback & cb =nullptr)<br>有参构造函数。需要显示指定Fd。 | 135| virtual | **~IOEventHandler**() | 136| void | **DisableAll**()<br>关闭所有事件监听。 | 137| void | **DisableWrite**()<br>关闭对“可写”事件的监听。 | 138| void | **EnableRead**()<br>开启对“可读”事件的监听。 | 139| void | **EnableWrite**()<br>开启对“可写”事件的监听。 | 140| EventCallback | **GetCallback**() const | 141| EventId | **GetEvents**() const | 142| int | **GetFd**() const | 143| bool | **IsActive**()<br>返回当前事件是否已启动。 | 144| IOEventHandler * | **Next**() const<br>获取链表中后一个事件的指针。 | 145| IOEventHandler & | **operator=**(const IOEventHandler && ) =delete | 146| IOEventHandler & | **operator=**(const IOEventHandler & ) =delete | 147| IOEventHandler * | **Prev**() const<br>获取链表中前一个事件的指针。 | 148| void | **SetCallback**(const EventCallback & cb)<br>设置具体响应行为/回调函数 | 149| void | **SetEvents**(EventId events)<br>设置被监听事件类型。 | 150| void | **SetFd**(int fd)<br>设置被监听对象Fd。 | 151| bool | **Start**(IOEventReactor * reactor)<br>启动当前事件监听。 | 152| bool | **Stop**(IOEventReactor * reactor)<br>停止当前事件监听 | 153| bool | **Update**(IOEventReactor * reactor)<br>更新当前事件状态。当指定事件类型、响应行为变化时需要对其进行更新。 | 154 155### OHOS::Utils::IOEventReactor 156#### 描述 157```cpp 158class OHOS::Utils::IOEventReactor; 159``` 160事件响应器类。其作为事件处理系统的中心调度器,负责管理外部添加的各个事件描述,按照描述添加对事件的监听、对各被监听对象进行轮询并对事件进行分发并处理。 161 162`#include <io_event_reactor.h>` 163 164#### 公共成员函数 165 166| 返回类型 | 名称 | 167| -------------- | -------------- | 168| | **IOEventHandler**()<br>默认构造函数。其Fd为-1。 | 169| | **IOEventHandler**(const IOEventHandler && ) =delete | 170| | **IOEventHandler**(const IOEventHandler & ) =delete | 171| | **IOEventHandler**(int fd, EventId events =Events::EVENT_NONE, const EventCallback & cb =nullptr)<br>有参构造函数。需要显示指定Fd。 | 172| virtual | **~IOEventHandler**() | 173| void | **DisableAll**()<br>关闭所有事件监听。 | 174| void | **DisableWrite**()<br>关闭对“可写”事件的监听。 | 175| void | **EnableRead**()<br>开启对“可读”事件的监听。 | 176| void | **EnableWrite**()<br>开启对“可写”事件的监听。 | 177| EventCallback | **GetCallback**() const | 178| EventId | **GetEvents**() const | 179| int | **GetFd**() const | 180| bool | **IsActive**()<br>返回当前事件是否已启动。 | 181| IOEventHandler * | **Next**() const<br>获取链表中后一个事件的指针。 | 182| IOEventHandler & | **operator=**(const IOEventHandler && ) =delete | 183| IOEventHandler & | **operator=**(const IOEventHandler & ) =delete | 184| IOEventHandler * | **Prev**() const<br>获取链表中前一个事件的指针。 | 185| void | **SetCallback**(const EventCallback & cb)<br>设置具体响应行为/回调函数 | 186| void | **SetEvents**(EventId events)<br>设置被监听事件类型。 | 187| void | **SetFd**(int fd)<br>设置被监听对象Fd。 | 188| bool | **Start**(IOEventReactor * reactor)<br>启动当前事件监听。 | 189| bool | **Stop**(IOEventReactor * reactor)<br>停止当前事件监听 | 190| bool | **Update**(IOEventReactor * reactor)<br>更新当前事件状态。当指定事件类型、响应行为变化时需要对其进行更新。 | 191 192## 使用示例 193 1941. 使用方法(伪代码) 195 196```c++ 197// IOEventHandler 可以按照业务需要进行继承拓展。如以针对linux底层timerfd定时器为例: 198class TimerFdHandler : public IOEventHandler { 199public: 200 using TimerEventCallback = std::function<void()>; 201 TimerFdHandler(int fd, const TimerEventCallback& cb); 202 ~TimerFdHandler() {} 203 bool Initialize(uint32_t interval); 204 void Uninitialize(); 205 void TimeOut(); 206 207private: 208 TimerEventCallback timerCallback_; 209}; 210``` 211 212```c++ 213 // 1. 首先创建定时器获取其Fd。 214 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 215 216 // 2. 创建IOEventHandler对象,对目标事件进行描述 217 std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 218 219 // 3. 创建IOEventReactor响应器对象,启动并使能其事件响应能力。 220 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 221 ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 222 reactor->EnableHandling(); 223 224 // 4. 根据业务需要,对IOEventHandler对象进行其他初始化操作。本例中是设置定时器的超时时间,定时器超时后会抛出"可读"事件,该事件可被捕获从而使响应器对其进行响应。 225 handler->Initialize(10); 226 227 // 5. 启动IOEventHandler对象(也可以使用IOEventReactor::AddHandler 方法启动) 228 handler->Start(reactor.get()); 229 230 // 6. 开启事件处理循环,`Run(int timeout)`方法使响应器循环进行事件处理,具体包括捕获事件以及对事件的响应过程。 231 std::thread loopThread([&reactor]{ 232 reactor->Run(-1); 233 }); 234 235 // 7. 定时器超时需要10ms,适当等待事件触发 236 std::this_thread::sleep_for(std::chrono::milliseconds(16)); 237 238 // 8. 确定响应结果, 本例中指定的响应行为 `&TimerCallback1`将对`g_data`加一,故可确定`g_data`的值判断是否响应成功。 239 // EXPECT_GE(g_data, 1); 240 241 // 9. 终止事件处理循环,`Terminate()`方法将使`Run()`方法退出,从而新线程执行完毕。 242 reactor->Terminate(); 243 loopThread.join(); 244 245 // 10. 事件描述对象生命周期结束时,会从当前响应器对象中移除,从而解除监听。响应器对象生命周期结束时,会清空当前注册的事件描述对象。 246 // Notes:尽管事件描述对象生命周期结束时会自动被移除,但手动停止事件描述对象能够提升运行效率,这是因为事件描述对象由于周期结束而被移除时,响应器对象将不会解除其注册的监听事件,该事件仍有可能被响应器捕获。 247 248 // 11. 所以这里手动停止事件描述对象。 249 handler->Stop(reactor.get()); 250``` 251 2522. 测试用例编译运行方法 253 254- 测试用例代码参见 base/test/unittest/common/utils_event_test.cpp 255 256- 使用开发者自测试框架,使用方法参见:[开发自测试执行框架-测试用例执行](https://gitee.com/openharmony/testfwk_developer_test#%E6%B5%8B%E8%AF%95%E7%94%A8%E4%BE%8B%E6%89%A7%E8%A1%8C) 257 258- 使用以下具体命令以运行事件处理系统对应测试用例 259 260```bash 261run -t UT -tp utils -ts UtilsEventTest 262```