1 /*
2  * Copyright (C) 2022-2023 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 #ifndef NET_MANAGER_TIMER_H
17 #define NET_MANAGER_TIMER_H
18 
19 #include <atomic>
20 #include <chrono>
21 #include <condition_variable>
22 #include <functional>
23 #include <memory>
24 #include <mutex>
25 #include <thread>
26 
27 #include "ffrt.h"
28 #include "ffrt_inner.h"
29 #include "net_mgr_log_wrapper.h"
30 
31 namespace OHOS {
32 namespace NetManagerStandard {
33 static constexpr const int TIMER_MAX_INTERVAL_MS = 200;
34 class FfrtTimer {
35 public:
FfrtTimer()36     FfrtTimer() : stopStatus_(true), tryStopFlag_(false) {}
37 
FfrtTimer(const FfrtTimer & timer)38     FfrtTimer(const FfrtTimer &timer)
39     {
40         stopStatus_ = timer.stopStatus_.load();
41         tryStopFlag_ = timer.tryStopFlag_.load();
42     }
43 
~FfrtTimer()44     ~FfrtTimer()
45     {
46         Stop();
47     }
48 
Start(int interval,std::function<void ()> taskFun)49     void Start(int interval, std::function<void()> taskFun)
50     {
51         if (stopStatus_ == false) {
52             return;
53         }
54         NETMGR_LOG_D("start thread...");
55         stopStatus_ = false;
56         std::function<void()> startTask = [this, interval, taskFun]() {
57             while (!tryStopFlag_) {
58                 OneTiming(interval);
59                 if (!tryStopFlag_) {
60                     taskFun();
61                 }
62             }
63 
64             std::lock_guard<ffrt::mutex> locker(mutex_);
65             stopStatus_ = true;
66             timerCond_.notify_one();
67         };
68         ffrt::submit(std::move(startTask), {}, {}, ffrt::task_attr().name("timeStartTask"));
69     }
70 
Stop()71     void Stop()
72     {
73         if (stopStatus_ || tryStopFlag_) {
74             return;
75         }
76         NETMGR_LOG_D("stop thread...");
77         tryStopFlag_ = true;
78         std::unique_lock<ffrt::mutex> locker(mutex_);
79         timerCond_.wait(locker, [this] { return stopStatus_ == true; });
80 
81         if (stopStatus_ == true) {
82             tryStopFlag_ = false;
83         }
84     }
85 
86 private:
OneTiming(int time)87     void OneTiming(int time)
88     {
89         int repeatCount = (time > TIMER_MAX_INTERVAL_MS) ? (time / TIMER_MAX_INTERVAL_MS) : 0;
90         int remainTime = (time > TIMER_MAX_INTERVAL_MS) ? (time % TIMER_MAX_INTERVAL_MS) : time;
91         while (!tryStopFlag_) {
92             if (repeatCount > 0) {
93                 ffrt::this_task::sleep_for(std::chrono::milliseconds(TIMER_MAX_INTERVAL_MS));
94             } else {
95                 if (remainTime) {
96                     ffrt::this_task::sleep_for(std::chrono::milliseconds(remainTime));
97                 }
98                 break;
99             }
100             repeatCount--;
101         }
102     }
103 
104 private:
105     std::atomic<bool> stopStatus_;
106     std::atomic<bool> tryStopFlag_;
107     ffrt::mutex mutex_;
108     ffrt::condition_variable timerCond_;
109 };
110 } // namespace NetManagerStandard
111 } // namespace OHOS
112 #endif // NET_MANAGER_TIMER_H
113