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
22 namespace OHOS {
23 namespace DistributedHardware {
24
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
Timer(std::string name, int32_t time, TimerCallback callback)29 Timer::Timer(std::string name, int32_t time, TimerCallback callback)
30 : timerName_(name), expire_(steadyClock::now()), state_(true), timeOut_(time), callback_(callback) {};
31
DmTimer()32 DmTimer::DmTimer()
33 {
34 }
35
~DmTimer()36 DmTimer::~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
StartTimer(std::string name, int32_t timeOut, TimerCallback callback)46 int32_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
DeleteTimer(std::string timerName)74 int32_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
DeleteAll()91 int32_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
TimerRunning()102 int32_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
DeleteVector(std::string name)148 void 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 }