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" 23namespace OHOS { 24namespace Sharing { 25 26#define TIMER_TIMEOUT 2 27TimeoutTimer::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 34TimeoutTimer::~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 57void 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 79void 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 93void 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 124void TimeoutTimer::SetTimeoutCallback(std::function<void()> callback) 125{ 126 callback_ = std::move(callback); 127} 128} // namespace Sharing 129} // namespace OHOS