• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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