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#include "dm_log.h" 17#include "dm_timer.h" 18 19#include <pthread.h> 20#include <thread> 21 22namespace OHOS { 23namespace DistributedHardware { 24 25constexpr const char* TIMER_RUNNING = "TimerRunning"; 26constexpr int32_t ERR_DM_INPUT_PARA_INVALID = -20006; 27constexpr int32_t DM_OK = 0; 28 29Timer::Timer(std::string name, int32_t time, TimerCallback callback) 30 : timerName_(name), expire_(steadyClock::now()), state_(true), timeOut_(time), callback_(callback) {}; 31 32DmTimer::DmTimer() 33{ 34} 35 36DmTimer::~DmTimer() 37{ 38 LOGI("DmTimer destructor"); 39 DeleteAll(); 40 if (timerState_) { 41 std::unique_lock<std::mutex> locker(timerStateMutex_); 42 stopTimerCondition_.wait(locker, [this] { return static_cast<bool>(!timerState_); }); 43 } 44} 45 46int32_t DmTimer::StartTimer(std::string name, int32_t timeOut, TimerCallback callback) 47{ 48 LOGI("DmTimer StartTimer %{public}s", name.c_str()); 49 if (name.empty() || timeOut <= MIN_TIME_OUT || timeOut > MAX_TIME_OUT || callback == nullptr) { 50 LOGI("DmTimer StartTimer input value invalid"); 51 return ERR_DM_INPUT_PARA_INVALID; 52 } 53 54 std::shared_ptr<Timer> timer = std::make_shared<Timer>(name, timeOut, callback); 55 { 56 std::lock_guard<std::mutex> locker(timerMutex_); 57 timerQueue_.push(timer); 58 timerVec_.emplace_back(timer); 59 } 60 61 if (timerState_) { 62 LOGI("DmTimer is running"); 63 return DM_OK; 64 } 65 66 TimerRunning(); 67 { 68 std::unique_lock<std::mutex> locker(timerStateMutex_); 69 runTimerCondition_.wait(locker, [this] { return static_cast<bool>(timerState_); }); 70 } 71 return DM_OK; 72} 73 74int32_t DmTimer::DeleteTimer(std::string timerName) 75{ 76 if (timerName.empty()) { 77 LOGE("DmTimer DeleteTimer timer is null"); 78 return ERR_DM_INPUT_PARA_INVALID; 79 } 80 81 LOGI("DmTimer DeleteTimer name %{public}s", timerName.c_str()); 82 std::lock_guard<std::mutex> locker(timerMutex_); 83 for (auto iter : timerVec_) { 84 if (iter != nullptr && iter->timerName_ == timerName) { 85 iter->state_ = false; 86 } 87 } 88 return DM_OK; 89} 90 91int32_t DmTimer::DeleteAll() 92{ 93 LOGI("DmTimer DeleteAll start"); 94 std::lock_guard<std::mutex> locker(timerMutex_); 95 for (auto iter : timerVec_) { 96 LOGI("DmTimer DeleteAll timer.name = %{public}s ", iter->timerName_.c_str()); 97 iter->state_ = false; 98 } 99 return DM_OK; 100} 101 102int32_t DmTimer::TimerRunning() 103{ 104 int32_t ret = pthread_setname_np(pthread_self(), TIMER_RUNNING); 105 if (ret != DM_OK) { 106 LOGE("TimerRunning setname failed."); 107 } 108 std::thread([this] () { 109 { 110 timerState_ = true; 111 std::unique_lock<std::mutex> locker(timerStateMutex_); 112 runTimerCondition_.notify_one(); 113 } 114 while (!timerQueue_.empty() && timerState_) { 115 std::this_thread::sleep_for(std::chrono::milliseconds(DELAY_TICK_MILLSECONDS)); 116 timerMutex_.lock(); 117 while (!timerQueue_.empty() && (std::chrono::duration_cast<timerDuration>(steadyClock::now() - 118 timerQueue_.top()->expire_).count() / MILLISECOND_TO_SECOND >= timerQueue_.top()->timeOut_ || 119 !timerQueue_.top()->state_)) { 120 std::string name = timerQueue_.top()->timerName_; 121 LOGI("DmTimer TimerRunning timer.name = %{public}s", name.c_str()); 122 TimerCallback callBack = nullptr; 123 if (timerQueue_.top()->state_) { 124 callBack = timerQueue_.top()->callback_; 125 } 126 timerQueue_.pop(); 127 DeleteVector(name); 128 timerMutex_.unlock(); 129 if (callBack != nullptr) { 130 callBack(name); 131 } 132 timerMutex_.lock(); 133 if (timerQueue_.empty()) { 134 break; 135 } 136 } 137 timerMutex_.unlock(); 138 } 139 { 140 timerState_ = false; 141 std::unique_lock<std::mutex> locker(timerStateMutex_); 142 stopTimerCondition_.notify_one(); 143 } 144 }).detach(); 145 return DM_OK; 146} 147 148void DmTimer::DeleteVector(std::string name) 149{ 150 for (auto iter = timerVec_.begin(); iter != timerVec_.end(); ++iter) { 151 if ((*iter)->timerName_ == name) { 152 timerVec_.erase(iter); 153 break; 154 } 155 } 156} 157} 158}