• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             UTILS_LOGE("epoll_create1 failed.");
51             return TIMER_ERR_BADF;
52         }
53     }
54     return TIMER_ERR_OK;
55 }
56 
CleanUp()57 void EventDemultiplexer::CleanUp()
58 {
59     if (epollFd_ != EPOLL_INVALID_FD) {
60         close(epollFd_);
61         epollFd_ = EPOLL_INVALID_FD;
62     }
63 }
64 
UpdateEventHandler(EventHandler * handler)65 uint32_t EventDemultiplexer::UpdateEventHandler(EventHandler* handler)
66 {
67     if (handler == nullptr) {
68         UTILS_LOGE("event handler is null.");
69         return TIMER_ERR_INVALID_VALUE;
70     }
71 
72     std::lock_guard<std::recursive_mutex> lock(mutex_);
73     auto itor = eventHandlers_.find(handler->GetHandle());
74     if (itor == eventHandlers_.end()) {
75         eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler));
76         return Update(EPOLL_CTL_ADD, handler);
77     }
78 
79     if (handler->Events() == EventReactor::NONE_EVENT) {
80         eventHandlers_.erase(itor);
81         return Update(EPOLL_CTL_DEL, handler);
82     }
83 
84     if (handler != itor->second) {
85         UTILS_LOGE("invalid event handler!");
86         return TIMER_ERR_DEAL_FAILED;
87     }
88     return Update(EPOLL_CTL_MOD, handler);
89 }
90 
RemoveEventHandler(EventHandler * handler)91 uint32_t EventDemultiplexer::RemoveEventHandler(EventHandler* handler)
92 {
93     if (handler == nullptr) {
94         UTILS_LOGE("event handler is null.");
95         return TIMER_ERR_INVALID_VALUE;
96     }
97 
98     std::lock_guard<std::recursive_mutex> lock(mutex_);
99     auto itor = eventHandlers_.find(handler->GetHandle());
100     if (itor == eventHandlers_.end()) {
101         return TIMER_ERR_OK;
102     }
103 
104     eventHandlers_.erase(itor);
105     if (static_cast<int>(eventHandlers_.size()) < maxEvents_) {
106         maxEvents_ = eventHandlers_.size() / HALF_OF_MAX_EVENT;
107     }
108 
109     return Update(EPOLL_CTL_DEL, handler);
110 }
111 
Update(int operation,EventHandler * handler)112 uint32_t EventDemultiplexer::Update(int operation, EventHandler* handler)
113 {
114     struct epoll_event event;
115     bzero(&event, sizeof(event));
116     event.events   = Reactor2Epoll(handler->Events());
117     event.data.ptr = reinterpret_cast<void*>(handler);
118 
119     if (epoll_ctl(epollFd_, operation, handler->GetHandle(), &event) != 0) {
120         UTILS_LOGE("epoll_ctl %{public}d  operation %{public}d on handle %{public}d failed",
121             epollFd_, operation, handler->GetHandle());
122         return TIMER_ERR_DEAL_FAILED;
123     }
124     return TIMER_ERR_OK;
125 }
126 
Polling(int timeout)127 void EventDemultiplexer::Polling(int timeout /* ms */)
128 {
129     std::vector<struct epoll_event> epollEvents(maxEvents_);
130     int nfds = epoll_wait(epollFd_, &epollEvents[0], static_cast<int>(epollEvents.size()), timeout);
131     if (nfds == 0) {
132         return;
133     }
134     if (nfds == -1) {
135         UTILS_LOGE("epoll_wait failed.");
136         return;
137     }
138 
139     for (int idx = 0; idx < nfds; ++idx) {
140         int events = epollEvents[idx].events;
141         void* ptr = epollEvents[idx].data.ptr;
142         auto handler = reinterpret_cast<EventHandler*>(ptr);
143         if (handler != nullptr) {
144             handler->HandleEvents(Epoll2Reactor(events));
145         }
146     }
147 
148     if (nfds == maxEvents_) {
149         maxEvents_ *= HALF_OF_MAX_EVENT;
150     }
151 }
152 
Epoll2Reactor(uint32_t epollEvents)153 uint32_t EventDemultiplexer::Epoll2Reactor(uint32_t epollEvents)
154 {
155     if ((epollEvents & EPOLLHUP) && !(epollEvents & EPOLLIN)) {
156         return EventReactor::CLOSE_EVENT;
157     }
158 
159     if (epollEvents & EPOLLERR) {
160         return EventReactor::ERROR_EVENT;
161     }
162 
163     if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
164         return EventReactor::READ_EVENT;
165     }
166 
167     if (epollEvents & EPOLLOUT) {
168         return EventReactor::WRITE_EVENT;
169     }
170 
171     return EventReactor::NONE_EVENT;
172 }
173 
Reactor2Epoll(uint32_t reactorEvent)174 uint32_t EventDemultiplexer::Reactor2Epoll(uint32_t reactorEvent)
175 {
176     switch (reactorEvent) {
177         case EventReactor::NONE_EVENT:
178             return TIMER_ERR_OK;
179         case EventReactor::READ_EVENT:
180             return EPOLLIN | EPOLLPRI;
181         case EventReactor::WRITE_EVENT:
182             return EPOLLOUT;
183         case EventReactor::READ_EVENT | EventReactor::WRITE_EVENT:
184             return EPOLLIN | EPOLLPRI | EPOLLOUT;
185         default:
186             UTILS_LOGE("invalid event %{public}u.", reactorEvent);
187             return TIMER_ERR_DEAL_FAILED;
188     }
189 }
190 
191 }
192 }
193