1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "event_demultiplexer.h"
17 #include "event_reactor.h"
18 #include "event_handler.h"
19 #include "common_timer_errors.h"
20 #include "utils_log.h"
21
22 #include <vector>
23 #include <cstdio>
24 #include <strings.h>
25 #include <unistd.h>
26 #include <sys/epoll.h>
27
28 namespace OHOS {
29 namespace Utils {
30
31 static const int EPOLL_MAX_EVENS_INIT = 8;
32 static const int HALF_OF_MAX_EVENT = 2;
33 static const int EPOLL_INVALID_FD = -1;
34
EventDemultiplexer()35 EventDemultiplexer::EventDemultiplexer()
36 : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENS_INIT), mutex_(), eventHandlers_()
37 {
38 }
39
~EventDemultiplexer()40 EventDemultiplexer::~EventDemultiplexer()
41 {
42 CleanUp();
43 }
44
StartUp()45 uint32_t EventDemultiplexer::StartUp()
46 {
47 if (epollFd_ < 0) {
48 epollFd_ = epoll_create1(EPOLL_CLOEXEC);
49 if (epollFd_ < 0) {
50 return TIMER_ERR_BADF;
51 }
52 }
53 return TIMER_ERR_OK;
54 }
55
CleanUp()56 void EventDemultiplexer::CleanUp()
57 {
58 if (epollFd_ != EPOLL_INVALID_FD) {
59 close(epollFd_);
60 epollFd_ = EPOLL_INVALID_FD;
61 }
62 }
63
UpdateEventHandler(EventHandler * handler)64 uint32_t EventDemultiplexer::UpdateEventHandler(EventHandler* handler)
65 {
66 if (handler == nullptr) {
67 return TIMER_ERR_INVALID_VALUE;
68 }
69
70 std::lock_guard<std::recursive_mutex> lock(mutex_);
71 auto itor = eventHandlers_.find(handler->GetHandle());
72 if (itor == eventHandlers_.end()) {
73 eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler));
74 return Update(EPOLL_CTL_ADD, handler);
75 }
76
77 if (handler->Events() == EventReactor::NONE_EVENT) {
78 eventHandlers_.erase(itor);
79 return Update(EPOLL_CTL_DEL, handler);
80 }
81
82 if (handler != itor->second) {
83 return TIMER_ERR_DEAL_FAILED;
84 }
85 return Update(EPOLL_CTL_MOD, handler);
86 }
87
RemoveEventHandler(EventHandler * handler)88 uint32_t EventDemultiplexer::RemoveEventHandler(EventHandler* handler)
89 {
90 if (handler == nullptr) {
91 return TIMER_ERR_INVALID_VALUE;
92 }
93
94 std::lock_guard<std::recursive_mutex> lock(mutex_);
95 auto itor = eventHandlers_.find(handler->GetHandle());
96 if (itor == eventHandlers_.end()) {
97 return TIMER_ERR_OK;
98 }
99
100 eventHandlers_.erase(itor);
101 if (static_cast<int>(eventHandlers_.size()) < maxEvents_) {
102 maxEvents_ = eventHandlers_.size() / HALF_OF_MAX_EVENT;
103 }
104
105 return Update(EPOLL_CTL_DEL, handler);
106 }
107
Update(int operation,EventHandler * handler)108 uint32_t EventDemultiplexer::Update(int operation, EventHandler* handler)
109 {
110 struct epoll_event event;
111 bzero(&event, sizeof(event));
112 event.events = Reactor2Epoll(handler->Events());
113 event.data.ptr = reinterpret_cast<void*>(handler);
114
115 if (epoll_ctl(epollFd_, operation, handler->GetHandle(), &event) != 0) {
116 UTILS_LOGD("epoll_ctl %{public}d operation %{public}d on handle %{public}d failed",
117 epollFd_, operation, handler->GetHandle());
118 return TIMER_ERR_DEAL_FAILED;
119 }
120 return TIMER_ERR_OK;
121 }
122
Polling(int timeout)123 void EventDemultiplexer::Polling(int timeout /* ms */)
124 {
125 std::vector<struct epoll_event> epollEvents(maxEvents_);
126 int nfds = epoll_wait(epollFd_, &epollEvents[0], static_cast<int>(epollEvents.size()), timeout);
127 if (nfds == 0) {
128 return;
129 }
130 if (nfds == -1) {
131 UTILS_LOGE("epoll_wait failed.");
132 return;
133 }
134
135 for (int idx = 0; idx < nfds; ++idx) {
136 int events = epollEvents[idx].events;
137 void* ptr = epollEvents[idx].data.ptr;
138 auto handler = reinterpret_cast<EventHandler*>(ptr);
139 if (handler != nullptr) {
140 handler->HandleEvents(Epoll2Reactor(events));
141 }
142 }
143
144 if (nfds == maxEvents_) {
145 maxEvents_ *= HALF_OF_MAX_EVENT;
146 }
147 }
148
Epoll2Reactor(uint32_t epollEvents)149 uint32_t EventDemultiplexer::Epoll2Reactor(uint32_t epollEvents)
150 {
151 if ((epollEvents & EPOLLHUP) && !(epollEvents & EPOLLIN)) {
152 return EventReactor::CLOSE_EVENT;
153 }
154
155 if (epollEvents & EPOLLERR) {
156 return EventReactor::ERROR_EVENT;
157 }
158
159 if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
160 return EventReactor::READ_EVENT;
161 }
162
163 if (epollEvents & EPOLLOUT) {
164 return EventReactor::WRITE_EVENT;
165 }
166
167 return EventReactor::NONE_EVENT;
168 }
169
Reactor2Epoll(uint32_t reactorEvent)170 uint32_t EventDemultiplexer::Reactor2Epoll(uint32_t reactorEvent)
171 {
172 switch (reactorEvent) {
173 case EventReactor::NONE_EVENT:
174 return TIMER_ERR_OK;
175 case EventReactor::READ_EVENT:
176 return EPOLLIN | EPOLLPRI;
177 case EventReactor::WRITE_EVENT:
178 return EPOLLOUT;
179 case EventReactor::READ_EVENT | EventReactor::WRITE_EVENT:
180 return EPOLLIN | EPOLLPRI | EPOLLOUT;
181 default:
182 UTILS_LOGD("invalid event %{public}u.", reactorEvent);
183 return TIMER_ERR_DEAL_FAILED;
184 }
185 }
186
187 }
188 }
189