179a732c7Sopenharmony_ci/*
279a732c7Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
379a732c7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
479a732c7Sopenharmony_ci * you may not use this file except in compliance with the License.
579a732c7Sopenharmony_ci * You may obtain a copy of the License at
679a732c7Sopenharmony_ci *
779a732c7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
879a732c7Sopenharmony_ci *
979a732c7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1079a732c7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1179a732c7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1279a732c7Sopenharmony_ci * See the License for the specific language governing permissions and
1379a732c7Sopenharmony_ci * limitations under the License.
1479a732c7Sopenharmony_ci */
1579a732c7Sopenharmony_ci
1679a732c7Sopenharmony_ci#include "dm_log.h"
1779a732c7Sopenharmony_ci#include "dm_timer.h"
1879a732c7Sopenharmony_ci
1979a732c7Sopenharmony_ci#include <pthread.h>
2079a732c7Sopenharmony_ci#include <thread>
2179a732c7Sopenharmony_ci
2279a732c7Sopenharmony_cinamespace OHOS {
2379a732c7Sopenharmony_cinamespace DistributedHardware {
2479a732c7Sopenharmony_ci
2579a732c7Sopenharmony_ciconstexpr const char* TIMER_RUNNING = "TimerRunning";
2679a732c7Sopenharmony_ciconstexpr int32_t ERR_DM_INPUT_PARA_INVALID = -20006;
2779a732c7Sopenharmony_ciconstexpr int32_t DM_OK = 0;
2879a732c7Sopenharmony_ci
2979a732c7Sopenharmony_ciTimer::Timer(std::string name, int32_t time, TimerCallback callback)
3079a732c7Sopenharmony_ci    : timerName_(name), expire_(steadyClock::now()), state_(true), timeOut_(time), callback_(callback) {};
3179a732c7Sopenharmony_ci
3279a732c7Sopenharmony_ciDmTimer::DmTimer()
3379a732c7Sopenharmony_ci{
3479a732c7Sopenharmony_ci}
3579a732c7Sopenharmony_ci
3679a732c7Sopenharmony_ciDmTimer::~DmTimer()
3779a732c7Sopenharmony_ci{
3879a732c7Sopenharmony_ci    LOGI("DmTimer destructor");
3979a732c7Sopenharmony_ci    DeleteAll();
4079a732c7Sopenharmony_ci    if (timerState_) {
4179a732c7Sopenharmony_ci        std::unique_lock<std::mutex> locker(timerStateMutex_);
4279a732c7Sopenharmony_ci        stopTimerCondition_.wait(locker, [this] { return static_cast<bool>(!timerState_); });
4379a732c7Sopenharmony_ci    }
4479a732c7Sopenharmony_ci}
4579a732c7Sopenharmony_ci
4679a732c7Sopenharmony_ciint32_t DmTimer::StartTimer(std::string name, int32_t timeOut, TimerCallback callback)
4779a732c7Sopenharmony_ci{
4879a732c7Sopenharmony_ci    LOGI("DmTimer StartTimer %{public}s", name.c_str());
4979a732c7Sopenharmony_ci    if (name.empty() || timeOut <= MIN_TIME_OUT || timeOut > MAX_TIME_OUT || callback == nullptr) {
5079a732c7Sopenharmony_ci        LOGI("DmTimer StartTimer input value invalid");
5179a732c7Sopenharmony_ci        return ERR_DM_INPUT_PARA_INVALID;
5279a732c7Sopenharmony_ci    }
5379a732c7Sopenharmony_ci
5479a732c7Sopenharmony_ci    std::shared_ptr<Timer> timer = std::make_shared<Timer>(name, timeOut, callback);
5579a732c7Sopenharmony_ci    {
5679a732c7Sopenharmony_ci        std::lock_guard<std::mutex> locker(timerMutex_);
5779a732c7Sopenharmony_ci        timerQueue_.push(timer);
5879a732c7Sopenharmony_ci        timerVec_.emplace_back(timer);
5979a732c7Sopenharmony_ci    }
6079a732c7Sopenharmony_ci
6179a732c7Sopenharmony_ci    if (timerState_) {
6279a732c7Sopenharmony_ci        LOGI("DmTimer is running");
6379a732c7Sopenharmony_ci        return DM_OK;
6479a732c7Sopenharmony_ci    }
6579a732c7Sopenharmony_ci
6679a732c7Sopenharmony_ci    TimerRunning();
6779a732c7Sopenharmony_ci    {
6879a732c7Sopenharmony_ci        std::unique_lock<std::mutex> locker(timerStateMutex_);
6979a732c7Sopenharmony_ci        runTimerCondition_.wait(locker, [this] { return static_cast<bool>(timerState_); });
7079a732c7Sopenharmony_ci    }
7179a732c7Sopenharmony_ci    return DM_OK;
7279a732c7Sopenharmony_ci}
7379a732c7Sopenharmony_ci
7479a732c7Sopenharmony_ciint32_t DmTimer::DeleteTimer(std::string timerName)
7579a732c7Sopenharmony_ci{
7679a732c7Sopenharmony_ci    if (timerName.empty()) {
7779a732c7Sopenharmony_ci        LOGE("DmTimer DeleteTimer timer is null");
7879a732c7Sopenharmony_ci        return ERR_DM_INPUT_PARA_INVALID;
7979a732c7Sopenharmony_ci    }
8079a732c7Sopenharmony_ci
8179a732c7Sopenharmony_ci    LOGI("DmTimer DeleteTimer name %{public}s", timerName.c_str());
8279a732c7Sopenharmony_ci    std::lock_guard<std::mutex> locker(timerMutex_);
8379a732c7Sopenharmony_ci    for (auto iter : timerVec_) {
8479a732c7Sopenharmony_ci        if (iter != nullptr && iter->timerName_ == timerName) {
8579a732c7Sopenharmony_ci            iter->state_ = false;
8679a732c7Sopenharmony_ci        }
8779a732c7Sopenharmony_ci    }
8879a732c7Sopenharmony_ci    return DM_OK;
8979a732c7Sopenharmony_ci}
9079a732c7Sopenharmony_ci
9179a732c7Sopenharmony_ciint32_t DmTimer::DeleteAll()
9279a732c7Sopenharmony_ci{
9379a732c7Sopenharmony_ci    LOGI("DmTimer DeleteAll start");
9479a732c7Sopenharmony_ci    std::lock_guard<std::mutex> locker(timerMutex_);
9579a732c7Sopenharmony_ci    for (auto iter : timerVec_) {
9679a732c7Sopenharmony_ci        LOGI("DmTimer DeleteAll timer.name = %{public}s ", iter->timerName_.c_str());
9779a732c7Sopenharmony_ci        iter->state_ = false;
9879a732c7Sopenharmony_ci    }
9979a732c7Sopenharmony_ci    return DM_OK;
10079a732c7Sopenharmony_ci}
10179a732c7Sopenharmony_ci
10279a732c7Sopenharmony_ciint32_t DmTimer::TimerRunning()
10379a732c7Sopenharmony_ci{
10479a732c7Sopenharmony_ci    int32_t ret = pthread_setname_np(pthread_self(), TIMER_RUNNING);
10579a732c7Sopenharmony_ci    if (ret != DM_OK) {
10679a732c7Sopenharmony_ci        LOGE("TimerRunning setname failed.");
10779a732c7Sopenharmony_ci    }
10879a732c7Sopenharmony_ci    std::thread([this] () {
10979a732c7Sopenharmony_ci        {
11079a732c7Sopenharmony_ci            timerState_ = true;
11179a732c7Sopenharmony_ci            std::unique_lock<std::mutex> locker(timerStateMutex_);
11279a732c7Sopenharmony_ci            runTimerCondition_.notify_one();
11379a732c7Sopenharmony_ci        }
11479a732c7Sopenharmony_ci        while (!timerQueue_.empty() && timerState_) {
11579a732c7Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TICK_MILLSECONDS));
11679a732c7Sopenharmony_ci            timerMutex_.lock();
11779a732c7Sopenharmony_ci            while (!timerQueue_.empty() && (std::chrono::duration_cast<timerDuration>(steadyClock::now() -
11879a732c7Sopenharmony_ci                timerQueue_.top()->expire_).count() / MILLISECOND_TO_SECOND >= timerQueue_.top()->timeOut_ ||
11979a732c7Sopenharmony_ci                !timerQueue_.top()->state_)) {
12079a732c7Sopenharmony_ci                std::string name = timerQueue_.top()->timerName_;
12179a732c7Sopenharmony_ci                LOGI("DmTimer TimerRunning timer.name = %{public}s", name.c_str());
12279a732c7Sopenharmony_ci                TimerCallback callBack = nullptr;
12379a732c7Sopenharmony_ci                if (timerQueue_.top()->state_) {
12479a732c7Sopenharmony_ci                    callBack = timerQueue_.top()->callback_;
12579a732c7Sopenharmony_ci                }
12679a732c7Sopenharmony_ci                timerQueue_.pop();
12779a732c7Sopenharmony_ci                DeleteVector(name);
12879a732c7Sopenharmony_ci                timerMutex_.unlock();
12979a732c7Sopenharmony_ci                if (callBack != nullptr) {
13079a732c7Sopenharmony_ci                    callBack(name);
13179a732c7Sopenharmony_ci                }
13279a732c7Sopenharmony_ci                timerMutex_.lock();
13379a732c7Sopenharmony_ci                if (timerQueue_.empty()) {
13479a732c7Sopenharmony_ci                    break;
13579a732c7Sopenharmony_ci                }
13679a732c7Sopenharmony_ci            }
13779a732c7Sopenharmony_ci            timerMutex_.unlock();
13879a732c7Sopenharmony_ci        }
13979a732c7Sopenharmony_ci        {
14079a732c7Sopenharmony_ci            timerState_ = false;
14179a732c7Sopenharmony_ci            std::unique_lock<std::mutex> locker(timerStateMutex_);
14279a732c7Sopenharmony_ci            stopTimerCondition_.notify_one();
14379a732c7Sopenharmony_ci        }
14479a732c7Sopenharmony_ci    }).detach();
14579a732c7Sopenharmony_ci    return DM_OK;
14679a732c7Sopenharmony_ci}
14779a732c7Sopenharmony_ci
14879a732c7Sopenharmony_civoid DmTimer::DeleteVector(std::string name)
14979a732c7Sopenharmony_ci{
15079a732c7Sopenharmony_ci    for (auto iter = timerVec_.begin(); iter != timerVec_.end(); ++iter) {
15179a732c7Sopenharmony_ci        if ((*iter)->timerName_ == name) {
15279a732c7Sopenharmony_ci            timerVec_.erase(iter);
15379a732c7Sopenharmony_ci            break;
15479a732c7Sopenharmony_ci        }
15579a732c7Sopenharmony_ci    }
15679a732c7Sopenharmony_ci}
15779a732c7Sopenharmony_ci}
15879a732c7Sopenharmony_ci}