1 /*
2 * Copyright (c) 2021-2022 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 "timer_manager.h"
17
18 namespace OHOS {
19 namespace MMI {
20 namespace {
21 constexpr int32_t MIN_DELAY = -1;
22 constexpr int32_t MIN_INTERVAL = 50;
23 constexpr int32_t MAX_INTERVAL = 4096;
24 constexpr int32_t MAX_TIMER_COUNT = 64;
25 constexpr int32_t NONEXISTENT_ID = -1;
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "TimerManager" };
27 } // namespace
28
TimerManager()29 TimerManager::TimerManager() {}
~TimerManager()30 TimerManager::~TimerManager() {}
31
AddTimer(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)32 int32_t TimerManager::AddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
33 {
34 return AddTimerInternal(intervalMs, repeatCount, callback);
35 }
36
RemoveTimer(int32_t timerId)37 int32_t TimerManager::RemoveTimer(int32_t timerId)
38 {
39 return RemoveTimerInternal(timerId);
40 }
41
ResetTimer(int32_t timerId)42 int32_t TimerManager::ResetTimer(int32_t timerId)
43 {
44 return ResetTimerInternal(timerId);
45 }
46
IsExist(int32_t timerId)47 bool TimerManager::IsExist(int32_t timerId)
48 {
49 return IsExistInternal(timerId);
50 }
51
CalcNextDelay()52 int32_t TimerManager::CalcNextDelay()
53 {
54 return CalcNextDelayInternal();
55 }
56
ProcessTimers()57 void TimerManager::ProcessTimers()
58 {
59 ProcessTimersInternal();
60 }
61
TakeNextTimerId()62 int32_t TimerManager::TakeNextTimerId()
63 {
64 uint64_t timerSlot = 0;
65 uint64_t one = 1;
66
67 for (const auto &timer : timers_) {
68 timerSlot |= (one << timer->id);
69 }
70
71 for (int32_t i = 0; i < MAX_TIMER_COUNT; i++) {
72 if ((timerSlot & (one << i)) == 0) {
73 return i;
74 }
75 }
76 return NONEXISTENT_ID;
77 }
78
AddTimerInternal(int32_t intervalMs,int32_t repeatCount,std::function<void ()> callback)79 int32_t TimerManager::AddTimerInternal(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback)
80 {
81 if (intervalMs < MIN_INTERVAL) {
82 intervalMs = MIN_INTERVAL;
83 } else if (intervalMs > MAX_INTERVAL) {
84 intervalMs = MAX_INTERVAL;
85 }
86 if (!callback) {
87 return NONEXISTENT_ID;
88 }
89 int32_t timerId = TakeNextTimerId();
90 if (timerId < 0) {
91 return NONEXISTENT_ID;
92 }
93 auto timer = std::make_unique<TimerItem>();
94 timer->id = timerId;
95 timer->intervalMs = intervalMs;
96 timer->repeatCount = repeatCount;
97 timer->callbackCount = 0;
98 auto nowTime = GetMillisTime();
99 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
100 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
101 return NONEXISTENT_ID;
102 }
103 timer->callback = callback;
104 InsertTimerInternal(timer);
105 return timerId;
106 }
107
RemoveTimerInternal(int32_t timerId)108 int32_t TimerManager::RemoveTimerInternal(int32_t timerId)
109 {
110 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
111 if ((*it)->id == timerId) {
112 timers_.erase(it);
113 return RET_OK;
114 }
115 }
116 return RET_ERR;
117 }
118
ResetTimerInternal(int32_t timerId)119 int32_t TimerManager::ResetTimerInternal(int32_t timerId)
120 {
121 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
122 if ((*it)->id == timerId) {
123 auto timer = std::move(*it);
124 timers_.erase(it);
125 auto nowTime = GetMillisTime();
126 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
127 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
128 return RET_ERR;
129 }
130 timer->callbackCount = 0;
131 InsertTimerInternal(timer);
132 return RET_OK;
133 }
134 }
135 return RET_ERR;
136 }
137
IsExistInternal(int32_t timerId)138 bool TimerManager::IsExistInternal(int32_t timerId)
139 {
140 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
141 if ((*it)->id == timerId) {
142 return true;
143 }
144 }
145 return false;
146 }
147
InsertTimerInternal(std::unique_ptr<TimerItem> & timer)148 void TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem>& timer)
149 {
150 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
151 if ((*it)->nextCallTime > timer->nextCallTime) {
152 timers_.insert(it, std::move(timer));
153 return;
154 }
155 }
156 timers_.push_back(std::move(timer));
157 }
158
CalcNextDelayInternal()159 int32_t TimerManager::CalcNextDelayInternal()
160 {
161 auto delay = MIN_DELAY;
162 if (!timers_.empty()) {
163 auto nowTime = GetMillisTime();
164 const auto& item = *timers_.begin();
165 if (nowTime >= item->nextCallTime) {
166 delay = 0;
167 } else {
168 delay = item->nextCallTime - nowTime;
169 }
170 }
171 return delay;
172 }
173
ProcessTimersInternal()174 void TimerManager::ProcessTimersInternal()
175 {
176 if (timers_.empty()) {
177 return;
178 }
179 auto nowTime = GetMillisTime();
180 for (;;) {
181 auto it = timers_.begin();
182 if (it == timers_.end()) {
183 break;
184 }
185 if ((*it)->nextCallTime > nowTime) {
186 break;
187 }
188 auto curTimer = std::move(*it);
189 timers_.erase(it);
190 ++curTimer->callbackCount;
191 if ((curTimer->repeatCount >= 1) && (curTimer->callbackCount >= curTimer->repeatCount)) {
192 curTimer->callback();
193 continue;
194 }
195 if (!AddInt64(nowTime, curTimer->intervalMs, curTimer->nextCallTime)) {
196 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
197 return;
198 }
199 auto callback = curTimer->callback;
200 InsertTimerInternal(curTimer);
201 callback();
202 }
203 }
204 } // namespace MMI
205 } // namespace OHOS
206