• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }