1/*
2 * Copyright (C) 2021 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 TELEPHONY_TIMER_H
17#define TELEPHONY_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 "telephony_log_wrapper.h"
28
29namespace OHOS {
30namespace Telephony {
31static constexpr const char* TIMER_START_THREAD = "timerStartThread";
32
33class Timer {
34public:
35    Timer() : stopStatus_(true), tryStopFlag_(false) {}
36
37    Timer(const Timer &timer)
38    {
39        stopStatus_ = timer.stopStatus_.load();
40        tryStopFlag_ = timer.tryStopFlag_.load();
41    }
42
43    ~Timer()
44    {
45        stop();
46    }
47
48    void start(int interval, std::function<void()> taskFun)
49    {
50        if (stopStatus_ == false) {
51            return;
52        }
53        stopStatus_ = false;
54        std::thread([this, interval, taskFun]() {
55            pthread_setname_np(pthread_self(), TIMER_START_THREAD);
56            while (!tryStopFlag_) {
57                std::this_thread::sleep_for(std::chrono::milliseconds(interval));
58                taskFun();
59            }
60            std::lock_guard<std::mutex> locker(mutex_);
61            stopStatus_ = true;
62            tryStopFlag_ = false;
63            timerCond_.notify_one();
64        }).detach();
65    }
66
67    void stop()
68    {
69        if (stopStatus_ || tryStopFlag_) {
70            return;
71        }
72        tryStopFlag_ = true;
73        {
74            std::unique_lock<std::mutex> locker(mutex_);
75            timerCond_.wait(locker, [this] { return stopStatus_ == true; });
76
77            if (stopStatus_ == true)
78                tryStopFlag_ = false;
79        }
80    }
81
82    void ThreadExit()
83    {
84        std::lock_guard<std::mutex> locker(mutex_);
85        stopStatus_ = true;
86        tryStopFlag_ = true;
87    }
88
89private:
90    std::atomic<bool> stopStatus_;
91    std::atomic<bool> tryStopFlag_;
92    std::mutex mutex_;
93    std::condition_variable timerCond_;
94};
95} // namespace Telephony
96} // namespace OHOS
97#endif // TELEPHONY_TIMER_H
98