1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License.
5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at
6b1b8bc3fSopenharmony_ci *
7b1b8bc3fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8b1b8bc3fSopenharmony_ci *
9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and
13b1b8bc3fSopenharmony_ci * limitations under the License.
14b1b8bc3fSopenharmony_ci */
15b1b8bc3fSopenharmony_ci
16b1b8bc3fSopenharmony_ci#ifndef NET_MANAGER_TIMER_H
17b1b8bc3fSopenharmony_ci#define NET_MANAGER_TIMER_H
18b1b8bc3fSopenharmony_ci
19b1b8bc3fSopenharmony_ci#include <atomic>
20b1b8bc3fSopenharmony_ci#include <chrono>
21b1b8bc3fSopenharmony_ci#include <condition_variable>
22b1b8bc3fSopenharmony_ci#include <functional>
23b1b8bc3fSopenharmony_ci#include <memory>
24b1b8bc3fSopenharmony_ci#include <mutex>
25b1b8bc3fSopenharmony_ci#include <thread>
26b1b8bc3fSopenharmony_ci
27b1b8bc3fSopenharmony_ci#include "ffrt.h"
28b1b8bc3fSopenharmony_ci#include "ffrt_inner.h"
29b1b8bc3fSopenharmony_ci#include "net_mgr_log_wrapper.h"
30b1b8bc3fSopenharmony_ci
31b1b8bc3fSopenharmony_cinamespace OHOS {
32b1b8bc3fSopenharmony_cinamespace NetManagerStandard {
33b1b8bc3fSopenharmony_cistatic constexpr const int TIMER_MAX_INTERVAL_MS = 200;
34b1b8bc3fSopenharmony_ciclass FfrtTimer {
35b1b8bc3fSopenharmony_cipublic:
36b1b8bc3fSopenharmony_ci    FfrtTimer() : stopStatus_(true), tryStopFlag_(false) {}
37b1b8bc3fSopenharmony_ci
38b1b8bc3fSopenharmony_ci    FfrtTimer(const FfrtTimer &timer)
39b1b8bc3fSopenharmony_ci    {
40b1b8bc3fSopenharmony_ci        stopStatus_ = timer.stopStatus_.load();
41b1b8bc3fSopenharmony_ci        tryStopFlag_ = timer.tryStopFlag_.load();
42b1b8bc3fSopenharmony_ci    }
43b1b8bc3fSopenharmony_ci
44b1b8bc3fSopenharmony_ci    ~FfrtTimer()
45b1b8bc3fSopenharmony_ci    {
46b1b8bc3fSopenharmony_ci        Stop();
47b1b8bc3fSopenharmony_ci    }
48b1b8bc3fSopenharmony_ci
49b1b8bc3fSopenharmony_ci    void Start(int interval, std::function<void()> taskFun)
50b1b8bc3fSopenharmony_ci    {
51b1b8bc3fSopenharmony_ci        if (stopStatus_ == false) {
52b1b8bc3fSopenharmony_ci            return;
53b1b8bc3fSopenharmony_ci        }
54b1b8bc3fSopenharmony_ci        NETMGR_LOG_D("start thread...");
55b1b8bc3fSopenharmony_ci        stopStatus_ = false;
56b1b8bc3fSopenharmony_ci        std::function<void()> startTask = [this, interval, taskFun]() {
57b1b8bc3fSopenharmony_ci            while (!tryStopFlag_) {
58b1b8bc3fSopenharmony_ci                OneTiming(interval);
59b1b8bc3fSopenharmony_ci                if (!tryStopFlag_) {
60b1b8bc3fSopenharmony_ci                    taskFun();
61b1b8bc3fSopenharmony_ci                }
62b1b8bc3fSopenharmony_ci            }
63b1b8bc3fSopenharmony_ci
64b1b8bc3fSopenharmony_ci            std::lock_guard<ffrt::mutex> locker(mutex_);
65b1b8bc3fSopenharmony_ci            stopStatus_ = true;
66b1b8bc3fSopenharmony_ci            timerCond_.notify_one();
67b1b8bc3fSopenharmony_ci        };
68b1b8bc3fSopenharmony_ci        ffrt::submit(std::move(startTask), {}, {}, ffrt::task_attr().name("timeStartTask"));
69b1b8bc3fSopenharmony_ci    }
70b1b8bc3fSopenharmony_ci
71b1b8bc3fSopenharmony_ci    void Stop()
72b1b8bc3fSopenharmony_ci    {
73b1b8bc3fSopenharmony_ci        if (stopStatus_ || tryStopFlag_) {
74b1b8bc3fSopenharmony_ci            return;
75b1b8bc3fSopenharmony_ci        }
76b1b8bc3fSopenharmony_ci        NETMGR_LOG_D("stop thread...");
77b1b8bc3fSopenharmony_ci        tryStopFlag_ = true;
78b1b8bc3fSopenharmony_ci        std::unique_lock<ffrt::mutex> locker(mutex_);
79b1b8bc3fSopenharmony_ci        timerCond_.wait(locker, [this] { return stopStatus_ == true; });
80b1b8bc3fSopenharmony_ci
81b1b8bc3fSopenharmony_ci        if (stopStatus_ == true) {
82b1b8bc3fSopenharmony_ci            tryStopFlag_ = false;
83b1b8bc3fSopenharmony_ci        }
84b1b8bc3fSopenharmony_ci    }
85b1b8bc3fSopenharmony_ci
86b1b8bc3fSopenharmony_ciprivate:
87b1b8bc3fSopenharmony_ci    void OneTiming(int time)
88b1b8bc3fSopenharmony_ci    {
89b1b8bc3fSopenharmony_ci        int repeatCount = (time > TIMER_MAX_INTERVAL_MS) ? (time / TIMER_MAX_INTERVAL_MS) : 0;
90b1b8bc3fSopenharmony_ci        int remainTime = (time > TIMER_MAX_INTERVAL_MS) ? (time % TIMER_MAX_INTERVAL_MS) : time;
91b1b8bc3fSopenharmony_ci        while (!tryStopFlag_) {
92b1b8bc3fSopenharmony_ci            if (repeatCount > 0) {
93b1b8bc3fSopenharmony_ci                ffrt::this_task::sleep_for(std::chrono::milliseconds(TIMER_MAX_INTERVAL_MS));
94b1b8bc3fSopenharmony_ci            } else {
95b1b8bc3fSopenharmony_ci                if (remainTime) {
96b1b8bc3fSopenharmony_ci                    ffrt::this_task::sleep_for(std::chrono::milliseconds(remainTime));
97b1b8bc3fSopenharmony_ci                }
98b1b8bc3fSopenharmony_ci                break;
99b1b8bc3fSopenharmony_ci            }
100b1b8bc3fSopenharmony_ci            repeatCount--;
101b1b8bc3fSopenharmony_ci        }
102b1b8bc3fSopenharmony_ci    }
103b1b8bc3fSopenharmony_ci
104b1b8bc3fSopenharmony_ciprivate:
105b1b8bc3fSopenharmony_ci    std::atomic<bool> stopStatus_;
106b1b8bc3fSopenharmony_ci    std::atomic<bool> tryStopFlag_;
107b1b8bc3fSopenharmony_ci    ffrt::mutex mutex_;
108b1b8bc3fSopenharmony_ci    ffrt::condition_variable timerCond_;
109b1b8bc3fSopenharmony_ci};
110b1b8bc3fSopenharmony_ci} // namespace NetManagerStandard
111b1b8bc3fSopenharmony_ci} // namespace OHOS
112b1b8bc3fSopenharmony_ci#endif // NET_MANAGER_TIMER_H
113