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