• 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 static const int INTERRUPTED_SYS_CALL = 4;
35 
EventDemultiplexer()36 EventDemultiplexer::EventDemultiplexer()
37     : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENS_INIT), mutex_(), eventHandlers_()
38 {
39 }
40 
~EventDemultiplexer()41 EventDemultiplexer::~EventDemultiplexer()
42 {
43     CleanUp();
44 }
45 
StartUp()46 uint32_t EventDemultiplexer::StartUp()
47 {
48     if (epollFd_ < 0) {
49         epollFd_ = epoll_create1(EPOLL_CLOEXEC);
50         if (epollFd_ < 0) {
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         return TIMER_ERR_INVALID_VALUE;
69     }
70 
71     std::lock_guard<std::recursive_mutex> lock(mutex_);
72     auto itor = eventHandlers_.find(handler->GetHandle());
73     if (itor == eventHandlers_.end()) {
74         eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler->shared_from_this()));
75         return Update(EPOLL_CTL_ADD, handler);
76     }
77 
78     if (handler->Events() == EventReactor::NONE_EVENT) {
79         eventHandlers_.erase(itor);
80         return Update(EPOLL_CTL_DEL, handler);
81     }
82 
83     if (handler != itor->second.get()) {
84         return TIMER_ERR_DEAL_FAILED;
85     }
86     return Update(EPOLL_CTL_MOD, handler);
87 }
88 
Update(int operation,EventHandler * handler)89 uint32_t EventDemultiplexer::Update(int operation, EventHandler* handler)
90 {
91     struct epoll_event event;
92     bzero(&event, sizeof(event));
93     event.events   = Reactor2Epoll(handler->Events());
94     event.data.fd = handler->GetHandle();
95 
96     if (epoll_ctl(epollFd_, operation, handler->GetHandle(), &event) != 0) {
97         UTILS_LOGD("epoll_ctl %{public}d  operation %{public}d on handle %{public}d failed",
98             epollFd_, operation, handler->GetHandle());
99         return TIMER_ERR_DEAL_FAILED;
100     }
101     return TIMER_ERR_OK;
102 }
103 
Polling(int timeout)104 void EventDemultiplexer::Polling(int timeout /* ms */)
105 {
106     std::vector<struct epoll_event> epollEvents(maxEvents_);
107     std::vector<std::shared_ptr<EventHandler>> taskQue;
108     std::vector<uint32_t> eventQue;
109 
110     int nfds = epoll_wait(epollFd_, &epollEvents[0], static_cast<int>(epollEvents.size()), timeout);
111     if (nfds == 0) {
112         return;
113     }
114     if (nfds == -1) {
115         if (errno != INTERRUPTED_SYS_CALL) {
116             UTILS_LOGE("epoll_wait failed, errno %{public}d", errno);
117         }
118         return;
119     }
120 
121     {
122         std::lock_guard<std::recursive_mutex> lock(mutex_);
123         for (int idx = 0; idx < nfds; ++idx) {
124             int targetFd = epollEvents[idx].data.fd;
125             uint32_t events = epollEvents[idx].events;
126 
127             auto itor = eventHandlers_.find(targetFd);
128             if (itor != eventHandlers_.end()) {
129                 taskQue.emplace_back(itor->second);
130                 eventQue.emplace_back(events);
131             }
132         }
133     }
134 
135     for (size_t idx = 0u; idx < taskQue.size() && idx < eventQue.size(); idx++) {
136         taskQue[idx]->HandleEvents(eventQue[idx]);
137     }
138 
139     if (nfds == maxEvents_) {
140         maxEvents_ *= HALF_OF_MAX_EVENT;
141     }
142 }
143 
Epoll2Reactor(uint32_t epollEvents)144 uint32_t EventDemultiplexer::Epoll2Reactor(uint32_t epollEvents)
145 {
146     if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
147         return EventReactor::READ_EVENT;
148     }
149 
150     return EventReactor::NONE_EVENT;
151 }
152 
Reactor2Epoll(uint32_t reactorEvent)153 uint32_t EventDemultiplexer::Reactor2Epoll(uint32_t reactorEvent)
154 {
155     switch (reactorEvent) {
156         case EventReactor::NONE_EVENT:
157             return TIMER_ERR_OK;
158         case EventReactor::READ_EVENT:
159             return EPOLLIN | EPOLLPRI;
160         default:
161             UTILS_LOGD("invalid event %{public}u.", reactorEvent);
162             return TIMER_ERR_DEAL_FAILED;
163     }
164 }
165 
166 }
167 }
168