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