1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#include "timer_manager.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG 19c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "TimerManager" 20c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN 21c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_SERVER 22c29fa5a6Sopenharmony_ci 23c29fa5a6Sopenharmony_cinamespace OHOS { 24c29fa5a6Sopenharmony_cinamespace MMI { 25c29fa5a6Sopenharmony_cinamespace { 26c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_DELAY { -1 }; 27c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_INTERVAL { 36 }; 28c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_INTERVAL_MS { 10000 }; 29c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_LONG_INTERVAL_MS { 30000 }; 30c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_TIMER_COUNT { 64 }; 31c29fa5a6Sopenharmony_ciconstexpr int32_t NONEXISTENT_ID { -1 }; 32c29fa5a6Sopenharmony_ci} // namespace 33c29fa5a6Sopenharmony_ci 34c29fa5a6Sopenharmony_ciTimerManager::TimerManager() {} 35c29fa5a6Sopenharmony_ciTimerManager::~TimerManager() {} 36c29fa5a6Sopenharmony_ci 37c29fa5a6Sopenharmony_ciint32_t TimerManager::AddTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 38c29fa5a6Sopenharmony_ci{ 39c29fa5a6Sopenharmony_ci if (intervalMs < MIN_INTERVAL) { 40c29fa5a6Sopenharmony_ci intervalMs = MIN_INTERVAL; 41c29fa5a6Sopenharmony_ci } else if (intervalMs > MAX_INTERVAL_MS) { 42c29fa5a6Sopenharmony_ci intervalMs = MAX_INTERVAL_MS; 43c29fa5a6Sopenharmony_ci } 44c29fa5a6Sopenharmony_ci return AddTimerInternal(intervalMs, repeatCount, callback); 45c29fa5a6Sopenharmony_ci} 46c29fa5a6Sopenharmony_ci 47c29fa5a6Sopenharmony_ciint32_t TimerManager::AddLongTimer(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 48c29fa5a6Sopenharmony_ci{ 49c29fa5a6Sopenharmony_ci if (intervalMs < MIN_INTERVAL) { 50c29fa5a6Sopenharmony_ci intervalMs = MIN_INTERVAL; 51c29fa5a6Sopenharmony_ci } else if (intervalMs > MAX_LONG_INTERVAL_MS) { 52c29fa5a6Sopenharmony_ci intervalMs = MAX_INTERVAL_MS; 53c29fa5a6Sopenharmony_ci } 54c29fa5a6Sopenharmony_ci return AddTimerInternal(intervalMs, repeatCount, callback); 55c29fa5a6Sopenharmony_ci} 56c29fa5a6Sopenharmony_ci 57c29fa5a6Sopenharmony_ciint32_t TimerManager::RemoveTimer(int32_t timerId) 58c29fa5a6Sopenharmony_ci{ 59c29fa5a6Sopenharmony_ci return RemoveTimerInternal(timerId); 60c29fa5a6Sopenharmony_ci} 61c29fa5a6Sopenharmony_ci 62c29fa5a6Sopenharmony_ciint32_t TimerManager::ResetTimer(int32_t timerId) 63c29fa5a6Sopenharmony_ci{ 64c29fa5a6Sopenharmony_ci return ResetTimerInternal(timerId); 65c29fa5a6Sopenharmony_ci} 66c29fa5a6Sopenharmony_ci 67c29fa5a6Sopenharmony_cibool TimerManager::IsExist(int32_t timerId) 68c29fa5a6Sopenharmony_ci{ 69c29fa5a6Sopenharmony_ci return IsExistInternal(timerId); 70c29fa5a6Sopenharmony_ci} 71c29fa5a6Sopenharmony_ci 72c29fa5a6Sopenharmony_ciint32_t TimerManager::CalcNextDelay() 73c29fa5a6Sopenharmony_ci{ 74c29fa5a6Sopenharmony_ci return CalcNextDelayInternal(); 75c29fa5a6Sopenharmony_ci} 76c29fa5a6Sopenharmony_ci 77c29fa5a6Sopenharmony_civoid TimerManager::ProcessTimers() 78c29fa5a6Sopenharmony_ci{ 79c29fa5a6Sopenharmony_ci ProcessTimersInternal(); 80c29fa5a6Sopenharmony_ci} 81c29fa5a6Sopenharmony_ci 82c29fa5a6Sopenharmony_ciint32_t TimerManager::TakeNextTimerId() 83c29fa5a6Sopenharmony_ci{ 84c29fa5a6Sopenharmony_ci uint64_t timerSlot = 0; 85c29fa5a6Sopenharmony_ci uint64_t one = 1; 86c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 87c29fa5a6Sopenharmony_ci for (const auto &timer : timers_) { 88c29fa5a6Sopenharmony_ci timerSlot |= (one << timer->id); 89c29fa5a6Sopenharmony_ci } 90c29fa5a6Sopenharmony_ci 91c29fa5a6Sopenharmony_ci for (int32_t i = 0; i < MAX_TIMER_COUNT; i++) { 92c29fa5a6Sopenharmony_ci if ((timerSlot & (one << i)) == 0) { 93c29fa5a6Sopenharmony_ci return i; 94c29fa5a6Sopenharmony_ci } 95c29fa5a6Sopenharmony_ci } 96c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 97c29fa5a6Sopenharmony_ci} 98c29fa5a6Sopenharmony_ci 99c29fa5a6Sopenharmony_ciint32_t TimerManager::AddTimerInternal(int32_t intervalMs, int32_t repeatCount, std::function<void()> callback) 100c29fa5a6Sopenharmony_ci{ 101c29fa5a6Sopenharmony_ci if (!callback) { 102c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 103c29fa5a6Sopenharmony_ci } 104c29fa5a6Sopenharmony_ci int32_t timerId = TakeNextTimerId(); 105c29fa5a6Sopenharmony_ci if (timerId < 0) { 106c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 107c29fa5a6Sopenharmony_ci } 108c29fa5a6Sopenharmony_ci auto timer = std::make_unique<TimerItem>(); 109c29fa5a6Sopenharmony_ci timer->id = timerId; 110c29fa5a6Sopenharmony_ci timer->intervalMs = intervalMs; 111c29fa5a6Sopenharmony_ci timer->repeatCount = repeatCount; 112c29fa5a6Sopenharmony_ci timer->callbackCount = 0; 113c29fa5a6Sopenharmony_ci auto nowTime = GetMillisTime(); 114c29fa5a6Sopenharmony_ci if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) { 115c29fa5a6Sopenharmony_ci MMI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 116c29fa5a6Sopenharmony_ci return NONEXISTENT_ID; 117c29fa5a6Sopenharmony_ci } 118c29fa5a6Sopenharmony_ci timer->callback = callback; 119c29fa5a6Sopenharmony_ci InsertTimerInternal(timer); 120c29fa5a6Sopenharmony_ci return timerId; 121c29fa5a6Sopenharmony_ci} 122c29fa5a6Sopenharmony_ci 123c29fa5a6Sopenharmony_ciint32_t TimerManager::RemoveTimerInternal(int32_t timerId) 124c29fa5a6Sopenharmony_ci{ 125c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 126c29fa5a6Sopenharmony_ci for (auto it = timers_.begin(); it != timers_.end(); ++it) { 127c29fa5a6Sopenharmony_ci if ((*it)->id == timerId) { 128c29fa5a6Sopenharmony_ci timers_.erase(it); 129c29fa5a6Sopenharmony_ci return RET_OK; 130c29fa5a6Sopenharmony_ci } 131c29fa5a6Sopenharmony_ci } 132c29fa5a6Sopenharmony_ci return RET_ERR; 133c29fa5a6Sopenharmony_ci} 134c29fa5a6Sopenharmony_ci 135c29fa5a6Sopenharmony_ciint32_t TimerManager::ResetTimerInternal(int32_t timerId) 136c29fa5a6Sopenharmony_ci{ 137c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 138c29fa5a6Sopenharmony_ci for (auto it = timers_.begin(); it != timers_.end(); ++it) { 139c29fa5a6Sopenharmony_ci if ((*it)->id == timerId) { 140c29fa5a6Sopenharmony_ci auto timer = std::move(*it); 141c29fa5a6Sopenharmony_ci timers_.erase(it); 142c29fa5a6Sopenharmony_ci auto nowTime = GetMillisTime(); 143c29fa5a6Sopenharmony_ci if (!AddInt64(nowTime, timer->intervalMs, timer->nextCallTime)) { 144c29fa5a6Sopenharmony_ci MMI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 145c29fa5a6Sopenharmony_ci return RET_ERR; 146c29fa5a6Sopenharmony_ci } 147c29fa5a6Sopenharmony_ci timer->callbackCount = 0; 148c29fa5a6Sopenharmony_ci InsertTimerInternal(timer); 149c29fa5a6Sopenharmony_ci return RET_OK; 150c29fa5a6Sopenharmony_ci } 151c29fa5a6Sopenharmony_ci } 152c29fa5a6Sopenharmony_ci return RET_ERR; 153c29fa5a6Sopenharmony_ci} 154c29fa5a6Sopenharmony_ci 155c29fa5a6Sopenharmony_cibool TimerManager::IsExistInternal(int32_t timerId) 156c29fa5a6Sopenharmony_ci{ 157c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 158c29fa5a6Sopenharmony_ci for (auto it = timers_.begin(); it != timers_.end(); ++it) { 159c29fa5a6Sopenharmony_ci if ((*it)->id == timerId) { 160c29fa5a6Sopenharmony_ci return true; 161c29fa5a6Sopenharmony_ci } 162c29fa5a6Sopenharmony_ci } 163c29fa5a6Sopenharmony_ci return false; 164c29fa5a6Sopenharmony_ci} 165c29fa5a6Sopenharmony_ci 166c29fa5a6Sopenharmony_civoid TimerManager::InsertTimerInternal(std::unique_ptr<TimerItem>& timer) 167c29fa5a6Sopenharmony_ci{ 168c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 169c29fa5a6Sopenharmony_ci for (auto it = timers_.begin(); it != timers_.end(); ++it) { 170c29fa5a6Sopenharmony_ci if ((*it)->nextCallTime > timer->nextCallTime) { 171c29fa5a6Sopenharmony_ci timers_.insert(it, std::move(timer)); 172c29fa5a6Sopenharmony_ci return; 173c29fa5a6Sopenharmony_ci } 174c29fa5a6Sopenharmony_ci } 175c29fa5a6Sopenharmony_ci timers_.push_back(std::move(timer)); 176c29fa5a6Sopenharmony_ci} 177c29fa5a6Sopenharmony_ci 178c29fa5a6Sopenharmony_ciint32_t TimerManager::CalcNextDelayInternal() 179c29fa5a6Sopenharmony_ci{ 180c29fa5a6Sopenharmony_ci auto delay = MIN_DELAY; 181c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 182c29fa5a6Sopenharmony_ci if (!timers_.empty()) { 183c29fa5a6Sopenharmony_ci auto nowTime = GetMillisTime(); 184c29fa5a6Sopenharmony_ci const auto& item = *timers_.begin(); 185c29fa5a6Sopenharmony_ci if (nowTime >= item->nextCallTime) { 186c29fa5a6Sopenharmony_ci delay = 0; 187c29fa5a6Sopenharmony_ci } else { 188c29fa5a6Sopenharmony_ci delay = item->nextCallTime - nowTime; 189c29fa5a6Sopenharmony_ci } 190c29fa5a6Sopenharmony_ci } 191c29fa5a6Sopenharmony_ci return delay; 192c29fa5a6Sopenharmony_ci} 193c29fa5a6Sopenharmony_ci 194c29fa5a6Sopenharmony_civoid TimerManager::ProcessTimersInternal() 195c29fa5a6Sopenharmony_ci{ 196c29fa5a6Sopenharmony_ci std::lock_guard<std::recursive_mutex> lock(timerMutex_); 197c29fa5a6Sopenharmony_ci if (timers_.empty()) { 198c29fa5a6Sopenharmony_ci return; 199c29fa5a6Sopenharmony_ci } 200c29fa5a6Sopenharmony_ci auto nowTime = GetMillisTime(); 201c29fa5a6Sopenharmony_ci for (;;) { 202c29fa5a6Sopenharmony_ci auto it = timers_.begin(); 203c29fa5a6Sopenharmony_ci if (it == timers_.end()) { 204c29fa5a6Sopenharmony_ci break; 205c29fa5a6Sopenharmony_ci } 206c29fa5a6Sopenharmony_ci if ((*it)->nextCallTime > nowTime) { 207c29fa5a6Sopenharmony_ci break; 208c29fa5a6Sopenharmony_ci } 209c29fa5a6Sopenharmony_ci auto curTimer = std::move(*it); 210c29fa5a6Sopenharmony_ci timers_.erase(it); 211c29fa5a6Sopenharmony_ci ++curTimer->callbackCount; 212c29fa5a6Sopenharmony_ci if ((curTimer->repeatCount >= 1) && (curTimer->callbackCount >= curTimer->repeatCount)) { 213c29fa5a6Sopenharmony_ci curTimer->callback(); 214c29fa5a6Sopenharmony_ci continue; 215c29fa5a6Sopenharmony_ci } 216c29fa5a6Sopenharmony_ci if (!AddInt64(curTimer->nextCallTime, curTimer->intervalMs, curTimer->nextCallTime)) { 217c29fa5a6Sopenharmony_ci MMI_HILOGE("The addition of nextCallTime in TimerItem overflows"); 218c29fa5a6Sopenharmony_ci return; 219c29fa5a6Sopenharmony_ci } 220c29fa5a6Sopenharmony_ci auto callback = curTimer->callback; 221c29fa5a6Sopenharmony_ci InsertTimerInternal(curTimer); 222c29fa5a6Sopenharmony_ci callback(); 223c29fa5a6Sopenharmony_ci } 224c29fa5a6Sopenharmony_ci} 225c29fa5a6Sopenharmony_ci} // namespace MMI 226c29fa5a6Sopenharmony_ci} // namespace OHOS 227