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#include "event_reactor.h"
16#include "event_handler.h"
17#include "event_demultiplexer.h"
18#include "timer_event_handler.h"
19#include "common_timer_errors.h"
20#include "utils_log.h"
21
22#include <cstdio>
23#include <unistd.h>
24#include <sys/syscall.h>
25
26namespace OHOS {
27namespace Utils {
28
29EventReactor::EventReactor()
30    :loopReady_(false), switch_(false), demultiplexer_(new EventDemultiplexer())
31{
32}
33
34EventReactor::~EventReactor()
35{
36}
37
38void EventReactor::UpdateEventHandler(EventHandler* handler)
39{
40    if ((handler != nullptr) && (handler->GetEventReactor() == this) && (demultiplexer_ != nullptr)) {
41        if (demultiplexer_->UpdateEventHandler(handler) != 0) {
42            UTILS_LOGE("updateEventHandler failed.");
43        }
44    }
45}
46
47uint32_t EventReactor::SetUp()
48{
49    if (demultiplexer_ == nullptr) {
50        return TIMER_ERR_INVALID_VALUE;
51    }
52
53    uint32_t ret = demultiplexer_->StartUp(); // return TIME_ERR_OK, if demultiplexer has been started.
54    if (ret != 0) {
55        UTILS_LOGE("demultiplexer startUp failed.");
56        return ret;
57    }
58
59    loopReady_ = true;
60    return TIMER_ERR_OK;
61}
62
63void EventReactor::CleanUp()
64{
65    std::lock_guard<std::recursive_mutex> lock(mutex_);
66    for (auto &itor : timerEventHandlers_) {
67        itor->Uninitialize();
68    }
69}
70
71void EventReactor::RunLoop(int timeout) const
72{
73    if (demultiplexer_ == nullptr) {
74        UTILS_LOGE("demultiplexer_ is nullptr.");
75        return;
76    }
77
78    while (loopReady_ && switch_) {
79        if (demultiplexer_->Polling(timeout) == EPOLL_CRITICAL_ERROR) {
80            UTILS_LOGE("polling critical error occure: %{public}d", timeout);
81            break;
82        }
83    }
84
85    loopReady_ = false;
86}
87
88void EventReactor::SwitchOn()
89{
90    switch_ = true;
91}
92
93void EventReactor::SwitchOff()
94{
95    switch_ = false;
96}
97
98uint32_t EventReactor::ScheduleTimer(const TimerCallback& cb, uint32_t interval, int& timerFd, bool once)
99{
100    std::lock_guard<std::recursive_mutex> lock(mutex_);
101    std::shared_ptr<TimerEventHandler> handler = std::make_shared<TimerEventHandler>(this, interval, once);
102    handler->SetTimerCallback(cb);
103    uint32_t ret = handler->Initialize();
104    if (ret != TIMER_ERR_OK) {
105        UTILS_LOGD("ScheduleTimer %{public}d initialize failed", interval);
106        return ret;
107    }
108
109    timerFd = handler->GetHandle();
110    timerEventHandlers_.push_back(handler);
111    return TIMER_ERR_OK;
112}
113
114void EventReactor::CancelTimer(int timerFd)
115{
116    UTILS_LOGD("Cancel timer, timerFd: %{public}d.", timerFd);
117    std::lock_guard<std::recursive_mutex> lock(mutex_);
118    auto itor = timerEventHandlers_.begin();
119    for (; itor != timerEventHandlers_.end(); ++itor) {
120        if ((*itor)->GetHandle() == timerFd) {
121            (*itor)->Uninitialize();
122            timerEventHandlers_.erase(itor);
123            return;
124        }
125    }
126}
127
128} // namespace Utils
129} // namespace OHOS
130