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