1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "timeout_timer.h"
17 #include <chrono>
18 #include <condition_variable>
19 #include <cstdio>
20 #include <cstring>
21 #include <sys/time.h>
22 #include "common/media_log.h"
23 namespace OHOS {
24 namespace Sharing {
25
26 #define TIMER_TIMEOUT 2
TimeoutTimer(std::string info)27 TimeoutTimer::TimeoutTimer(std::string info)
28 {
29 SHARING_LOGD("trace.");
30 thread_ = std::make_unique<std::thread>(&TimeoutTimer::MainLoop, this);
31 pthread_setname_np(thread_->native_handle(), info.c_str());
32 }
33
~TimeoutTimer()34 TimeoutTimer::~TimeoutTimer()
35 {
36 SHARING_LOGD("dtor in %{public}d.", state_);
37 {
38 std::unique_lock<std::mutex> taskLock(taskMutex_);
39 if (state_ == State::WAITING) {
40 state_ = State::EXITED;
41 taskSignal_.notify_all();
42 } else if (state_ == State::WORKING) {
43 state_ = State::EXITED;
44 cancelSignal_.notify_all();
45 } else {
46 state_ = State::EXITED;
47 }
48 }
49
50 SHARING_LOGD("thread join %{public}d.", state_);
51 if (thread_->joinable()) {
52 thread_->join();
53 }
54 SHARING_LOGD("dtor out %{public}d.", state_);
55 }
56
StartTimer(int timeout,std::string info,std::function<void ()> callback,bool reuse)57 void TimeoutTimer::StartTimer(int timeout, std::string info, std::function<void()> callback, bool reuse)
58 {
59 SHARING_LOGD("add timeout timer (%{public}s).", info.c_str());
60 std::lock_guard<std::mutex> lock(taskMutex_);
61 reuse_ = reuse;
62 timeout_ = timeout;
63 if (state_ == State::WORKING) {
64 SHARING_LOGD("cancel timeout timer (%{public}s).", taskName_.c_str());
65 state_ = State::CANCELLED;
66 cancelSignal_.notify_all();
67
68 std::unique_lock<std::mutex> waitLock(waitMutex_);
69 waitSignal_.wait_for(waitLock, std::chrono::milliseconds(TIMER_TIMEOUT));
70 }
71 taskName_ = std::move(info);
72 if (callback) {
73 callback_ = std::move(callback);
74 }
75 taskSignal_.notify_all();
76 SHARING_LOGD("start timeout timer (%{public}s) leave.", info.c_str());
77 }
78
StopTimer()79 void TimeoutTimer::StopTimer()
80 {
81 SHARING_LOGD("cancel timeout timer (%{public}s).", taskName_.c_str());
82 std::lock_guard<std::mutex> lock(taskMutex_);
83
84 if (state_ == State::WORKING) {
85 state_ = State::CANCELLED;
86 cancelSignal_.notify_all();
87 std::unique_lock<std::mutex> waitLock(waitMutex_);
88 waitSignal_.wait_for(waitLock, std::chrono::milliseconds(TIMER_TIMEOUT));
89 }
90 SHARING_LOGD("cancel timeout timer (%{public}s) leave.", taskName_.c_str());
91 }
92
MainLoop()93 void TimeoutTimer::MainLoop()
94 {
95 SHARING_LOGD("trace.");
96 while (state_ != State::EXITED) {
97 std::unique_lock<std::mutex> taskLock(taskMutex_);
98 if (state_ == State::EXITED) {
99 break;
100 }
101
102 state_ = State::WAITING;
103 waitSignal_.notify_all();
104 if (!reuse_) {
105 taskSignal_.wait(taskLock);
106 }
107
108 if (state_ == State::EXITED) {
109 break;
110 }
111
112 state_ = State::WORKING;
113 SHARING_LOGI("start timeout timer(%{public}s).", taskName_.c_str());
114 cancelSignal_.wait_for(taskLock, std::chrono::seconds(timeout_));
115 if (state_ == State::WORKING && callback_) {
116 SHARING_LOGI("invoke timeout timer(%{public}s) callback.", taskName_.c_str());
117 callback_();
118 }
119 SHARING_LOGI("end timeout timer(%{public}s).", taskName_.c_str());
120 }
121 SHARING_LOGD("exit.");
122 }
123
SetTimeoutCallback(std::function<void ()> callback)124 void TimeoutTimer::SetTimeoutCallback(std::function<void()> callback)
125 {
126 callback_ = std::move(callback);
127 }
128 } // namespace Sharing
129 } // namespace OHOS