1e0e9324cSopenharmony_ci/* 2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License. 5e0e9324cSopenharmony_ci * You may obtain a copy of the License at 6e0e9324cSopenharmony_ci * 7e0e9324cSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0e9324cSopenharmony_ci * 9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and 13e0e9324cSopenharmony_ci * limitations under the License. 14e0e9324cSopenharmony_ci */ 15e0e9324cSopenharmony_ci 16e0e9324cSopenharmony_ci#include "timeout_timer.h" 17e0e9324cSopenharmony_ci#include <chrono> 18e0e9324cSopenharmony_ci#include <condition_variable> 19e0e9324cSopenharmony_ci#include <cstdio> 20e0e9324cSopenharmony_ci#include <cstring> 21e0e9324cSopenharmony_ci#include <sys/time.h> 22e0e9324cSopenharmony_ci#include "common/media_log.h" 23e0e9324cSopenharmony_cinamespace OHOS { 24e0e9324cSopenharmony_cinamespace Sharing { 25e0e9324cSopenharmony_ci 26e0e9324cSopenharmony_ci#define TIMER_TIMEOUT 2 27e0e9324cSopenharmony_ciTimeoutTimer::TimeoutTimer(std::string info) 28e0e9324cSopenharmony_ci{ 29e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 30e0e9324cSopenharmony_ci thread_ = std::make_unique<std::thread>(&TimeoutTimer::MainLoop, this); 31e0e9324cSopenharmony_ci pthread_setname_np(thread_->native_handle(), info.c_str()); 32e0e9324cSopenharmony_ci} 33e0e9324cSopenharmony_ci 34e0e9324cSopenharmony_ciTimeoutTimer::~TimeoutTimer() 35e0e9324cSopenharmony_ci{ 36e0e9324cSopenharmony_ci SHARING_LOGD("dtor in %{public}d.", state_); 37e0e9324cSopenharmony_ci { 38e0e9324cSopenharmony_ci std::unique_lock<std::mutex> taskLock(taskMutex_); 39e0e9324cSopenharmony_ci if (state_ == State::WAITING) { 40e0e9324cSopenharmony_ci state_ = State::EXITED; 41e0e9324cSopenharmony_ci taskSignal_.notify_all(); 42e0e9324cSopenharmony_ci } else if (state_ == State::WORKING) { 43e0e9324cSopenharmony_ci state_ = State::EXITED; 44e0e9324cSopenharmony_ci cancelSignal_.notify_all(); 45e0e9324cSopenharmony_ci } else { 46e0e9324cSopenharmony_ci state_ = State::EXITED; 47e0e9324cSopenharmony_ci } 48e0e9324cSopenharmony_ci } 49e0e9324cSopenharmony_ci 50e0e9324cSopenharmony_ci SHARING_LOGD("thread join %{public}d.", state_); 51e0e9324cSopenharmony_ci if (thread_->joinable()) { 52e0e9324cSopenharmony_ci thread_->join(); 53e0e9324cSopenharmony_ci } 54e0e9324cSopenharmony_ci SHARING_LOGD("dtor out %{public}d.", state_); 55e0e9324cSopenharmony_ci} 56e0e9324cSopenharmony_ci 57e0e9324cSopenharmony_civoid TimeoutTimer::StartTimer(int timeout, std::string info, std::function<void()> callback, bool reuse) 58e0e9324cSopenharmony_ci{ 59e0e9324cSopenharmony_ci SHARING_LOGD("add timeout timer (%{public}s).", info.c_str()); 60e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(taskMutex_); 61e0e9324cSopenharmony_ci reuse_ = reuse; 62e0e9324cSopenharmony_ci timeout_ = timeout; 63e0e9324cSopenharmony_ci if (state_ == State::WORKING) { 64e0e9324cSopenharmony_ci SHARING_LOGD("cancel timeout timer (%{public}s).", taskName_.c_str()); 65e0e9324cSopenharmony_ci state_ = State::CANCELLED; 66e0e9324cSopenharmony_ci cancelSignal_.notify_all(); 67e0e9324cSopenharmony_ci 68e0e9324cSopenharmony_ci std::unique_lock<std::mutex> waitLock(waitMutex_); 69e0e9324cSopenharmony_ci waitSignal_.wait_for(waitLock, std::chrono::milliseconds(TIMER_TIMEOUT)); 70e0e9324cSopenharmony_ci } 71e0e9324cSopenharmony_ci taskName_ = std::move(info); 72e0e9324cSopenharmony_ci if (callback) { 73e0e9324cSopenharmony_ci callback_ = std::move(callback); 74e0e9324cSopenharmony_ci } 75e0e9324cSopenharmony_ci taskSignal_.notify_all(); 76e0e9324cSopenharmony_ci SHARING_LOGD("start timeout timer (%{public}s) leave.", info.c_str()); 77e0e9324cSopenharmony_ci} 78e0e9324cSopenharmony_ci 79e0e9324cSopenharmony_civoid TimeoutTimer::StopTimer() 80e0e9324cSopenharmony_ci{ 81e0e9324cSopenharmony_ci SHARING_LOGD("cancel timeout timer (%{public}s).", taskName_.c_str()); 82e0e9324cSopenharmony_ci std::lock_guard<std::mutex> lock(taskMutex_); 83e0e9324cSopenharmony_ci 84e0e9324cSopenharmony_ci if (state_ == State::WORKING) { 85e0e9324cSopenharmony_ci state_ = State::CANCELLED; 86e0e9324cSopenharmony_ci cancelSignal_.notify_all(); 87e0e9324cSopenharmony_ci std::unique_lock<std::mutex> waitLock(waitMutex_); 88e0e9324cSopenharmony_ci waitSignal_.wait_for(waitLock, std::chrono::milliseconds(TIMER_TIMEOUT)); 89e0e9324cSopenharmony_ci } 90e0e9324cSopenharmony_ci SHARING_LOGD("cancel timeout timer (%{public}s) leave.", taskName_.c_str()); 91e0e9324cSopenharmony_ci} 92e0e9324cSopenharmony_ci 93e0e9324cSopenharmony_civoid TimeoutTimer::MainLoop() 94e0e9324cSopenharmony_ci{ 95e0e9324cSopenharmony_ci SHARING_LOGD("trace."); 96e0e9324cSopenharmony_ci while (state_ != State::EXITED) { 97e0e9324cSopenharmony_ci std::unique_lock<std::mutex> taskLock(taskMutex_); 98e0e9324cSopenharmony_ci if (state_ == State::EXITED) { 99e0e9324cSopenharmony_ci break; 100e0e9324cSopenharmony_ci } 101e0e9324cSopenharmony_ci 102e0e9324cSopenharmony_ci state_ = State::WAITING; 103e0e9324cSopenharmony_ci waitSignal_.notify_all(); 104e0e9324cSopenharmony_ci if (!reuse_) { 105e0e9324cSopenharmony_ci taskSignal_.wait(taskLock); 106e0e9324cSopenharmony_ci } 107e0e9324cSopenharmony_ci 108e0e9324cSopenharmony_ci if (state_ == State::EXITED) { 109e0e9324cSopenharmony_ci break; 110e0e9324cSopenharmony_ci } 111e0e9324cSopenharmony_ci 112e0e9324cSopenharmony_ci state_ = State::WORKING; 113e0e9324cSopenharmony_ci SHARING_LOGI("start timeout timer(%{public}s).", taskName_.c_str()); 114e0e9324cSopenharmony_ci cancelSignal_.wait_for(taskLock, std::chrono::seconds(timeout_)); 115e0e9324cSopenharmony_ci if (state_ == State::WORKING && callback_) { 116e0e9324cSopenharmony_ci SHARING_LOGI("invoke timeout timer(%{public}s) callback.", taskName_.c_str()); 117e0e9324cSopenharmony_ci callback_(); 118e0e9324cSopenharmony_ci } 119e0e9324cSopenharmony_ci SHARING_LOGI("end timeout timer(%{public}s).", taskName_.c_str()); 120e0e9324cSopenharmony_ci } 121e0e9324cSopenharmony_ci SHARING_LOGD("exit."); 122e0e9324cSopenharmony_ci} 123e0e9324cSopenharmony_ci 124e0e9324cSopenharmony_civoid TimeoutTimer::SetTimeoutCallback(std::function<void()> callback) 125e0e9324cSopenharmony_ci{ 126e0e9324cSopenharmony_ci callback_ = std::move(callback); 127e0e9324cSopenharmony_ci} 128e0e9324cSopenharmony_ci} // namespace Sharing 129e0e9324cSopenharmony_ci} // namespace OHOS