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 auto timer = std::make_unique<TimerItem>();
105 timer->intervalMs = intervalMs;
106 timer->repeatCount = repeatCount;
107 timer->callbackCount = 0;
108 auto nowTime = GetMillisTime();
109 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
110 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
111 return NONEXISTENT_ID;
112 }
113 timer->callback = callback;
114 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
115 int32_t timerId = TakeNextTimerId();
116 if (timerId < 0) {
117 return NONEXISTENT_ID;
118 }
119 timer->id = timerId;
120 InsertTimerInternal(timer);
121 return timerId;
122 }
123
RemoveTimerInternal(int32_t timerId)124 int32_t TimerManager::RemoveTimerInternal(int32_t timerId)
125 {
126 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
127 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
128 if ((*it)->id == timerId) {
129 timers_.erase(it);
130 return RET_OK;
131 }
132 }
133 return RET_ERR;
134 }
135
ResetTimerInternal(int32_t timerId)136 int32_t TimerManager::ResetTimerInternal(int32_t timerId)
137 {
138 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
139 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
140 if ((*it)->id == timerId) {
141 auto timer = std::move(*it);
142 timers_.erase(it);
143 auto nowTime = GetMillisTime();
144 if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) {
145 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
146 return RET_ERR;
147 }
148 timer->callbackCount = 0;
149 InsertTimerInternal(timer);
150 return RET_OK;
151 }
152 }
153 return RET_ERR;
154 }
155
IsExistInternal(int32_t timerId)156 bool TimerManager::IsExistInternal(int32_t timerId)
157 {
158 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
159 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
160 if ((*it)->id == timerId) {
161 return true;
162 }
163 }
164 return false;
165 }
166
InsertTimerInternal(std::unique_ptr<TimerItem> & timer)167 void TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem>& timer)
168 {
169 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
170 for (auto it = timers_.begin(); it != timers_.end(); ++it) {
171 if ((*it)->nextCallTime > timer->nextCallTime) {
172 timers_.insert(it, std::move(timer));
173 return;
174 }
175 }
176 timers_.push_back(std::move(timer));
177 }
178
CalcNextDelayInternal()179 int32_t TimerManager::CalcNextDelayInternal()
180 {
181 auto delay = MIN_DELAY;
182 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
183 if (!timers_.empty()) {
184 auto nowTime = GetMillisTime();
185 const auto& item = *timers_.begin();
186 if (nowTime >= item->nextCallTime) {
187 delay = 0;
188 } else {
189 delay = item->nextCallTime - nowTime;
190 }
191 }
192 return delay;
193 }
194
ProcessTimersInternal()195 void TimerManager::ProcessTimersInternal()
196 {
197 std::lock_guard<std::recursive_mutex> lock(timerMutex_);
198 if (timers_.empty()) {
199 return;
200 }
201 auto nowTime = GetMillisTime();
202 for (;;) {
203 auto it = timers_.begin();
204 if (it == timers_.end()) {
205 break;
206 }
207 if ((*it)->nextCallTime > nowTime) {
208 break;
209 }
210 auto curTimer = std::move(*it);
211 timers_.erase(it);
212 ++curTimer->callbackCount;
213 if ((curTimer->repeatCount >= 1) && (curTimer->callbackCount >= curTimer->repeatCount)) {
214 curTimer->callback();
215 continue;
216 }
217 if (!AddInt64(curTimer->nextCallTime, curTimer->intervalMs, curTimer->nextCallTime)) {
218 MMI_HILOGE("The addition of nextCallTime in TimerItem overflows");
219 return;
220 }
221 auto callback = curTimer->callback;
222 InsertTimerInternal(curTimer);
223 callback();
224 }
225 }
226 } // namespace MMI
227 } // namespace OHOS
228