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