1da853ecaSopenharmony_ci/* 2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License. 5da853ecaSopenharmony_ci * You may obtain a copy of the License at 6da853ecaSopenharmony_ci * 7da853ecaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8da853ecaSopenharmony_ci * 9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and 13da853ecaSopenharmony_ci * limitations under the License. 14da853ecaSopenharmony_ci */ 15da853ecaSopenharmony_ci 16da853ecaSopenharmony_ci#include "task_thread.h" 17da853ecaSopenharmony_ci#include "avcodec_log.h" 18da853ecaSopenharmony_ci 19da853ecaSopenharmony_cinamespace { 20da853ecaSopenharmony_ci constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "TaskThread"}; 21da853ecaSopenharmony_ci constexpr uint8_t LOGD_FREQUENCY = 100; 22da853ecaSopenharmony_ci} 23da853ecaSopenharmony_cinamespace OHOS { 24da853ecaSopenharmony_cinamespace MediaAVCodec { 25da853ecaSopenharmony_ciTaskThread::TaskThread(std::string_view name) : name_(name), runningState_(RunningState::STOPPED), loop_(nullptr) 26da853ecaSopenharmony_ci{ 27da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s ctor called", name_.data()); 28da853ecaSopenharmony_ci} 29da853ecaSopenharmony_ci 30da853ecaSopenharmony_ciTaskThread::TaskThread(std::string_view name, std::function<void()> handler) : TaskThread(name) 31da853ecaSopenharmony_ci{ 32da853ecaSopenharmony_ci handler_ = std::move(handler); 33da853ecaSopenharmony_ci loop_ = std::make_unique<std::thread>(&TaskThread::Run, this); 34da853ecaSopenharmony_ci} 35da853ecaSopenharmony_ci 36da853ecaSopenharmony_ciTaskThread::~TaskThread() 37da853ecaSopenharmony_ci{ 38da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s dtor called", name_.data()); 39da853ecaSopenharmony_ci runningState_ = RunningState::STOPPED; 40da853ecaSopenharmony_ci syncCond_.notify_all(); 41da853ecaSopenharmony_ci 42da853ecaSopenharmony_ci if (loop_ != nullptr) { 43da853ecaSopenharmony_ci if (loop_->joinable()) { 44da853ecaSopenharmony_ci loop_->join(); 45da853ecaSopenharmony_ci } 46da853ecaSopenharmony_ci loop_ = nullptr; 47da853ecaSopenharmony_ci } 48da853ecaSopenharmony_ci} 49da853ecaSopenharmony_ci 50da853ecaSopenharmony_civoid TaskThread::Start() 51da853ecaSopenharmony_ci{ 52da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 53da853ecaSopenharmony_ci if (runningState_.load() == RunningState::STOPPING) { 54da853ecaSopenharmony_ci syncCond_.wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; }); 55da853ecaSopenharmony_ci } 56da853ecaSopenharmony_ci if (runningState_.load() == RunningState::STOPPED) { 57da853ecaSopenharmony_ci if (loop_ != nullptr) { 58da853ecaSopenharmony_ci if (loop_->joinable()) { 59da853ecaSopenharmony_ci loop_->join(); 60da853ecaSopenharmony_ci } 61da853ecaSopenharmony_ci loop_ = nullptr; 62da853ecaSopenharmony_ci } 63da853ecaSopenharmony_ci } 64da853ecaSopenharmony_ci 65da853ecaSopenharmony_ci runningState_ = RunningState::STARTED; 66da853ecaSopenharmony_ci 67da853ecaSopenharmony_ci if (!loop_) { // thread not exist 68da853ecaSopenharmony_ci loop_ = std::make_unique<std::thread>(&TaskThread::Run, this); 69da853ecaSopenharmony_ci } 70da853ecaSopenharmony_ci syncCond_.notify_all(); 71da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s start called", name_.data()); 72da853ecaSopenharmony_ci} 73da853ecaSopenharmony_ci 74da853ecaSopenharmony_civoid TaskThread::Stop() 75da853ecaSopenharmony_ci{ 76da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s stop entered, current state: %{public}d", name_.data(), runningState_.load()); 77da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 78da853ecaSopenharmony_ci if (runningState_.load() != RunningState::STOPPED) { 79da853ecaSopenharmony_ci runningState_ = RunningState::STOPPING; 80da853ecaSopenharmony_ci syncCond_.notify_all(); 81da853ecaSopenharmony_ci syncCond_.wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; }); 82da853ecaSopenharmony_ci if (loop_ != nullptr) { 83da853ecaSopenharmony_ci if (loop_->joinable()) { 84da853ecaSopenharmony_ci loop_->join(); 85da853ecaSopenharmony_ci } 86da853ecaSopenharmony_ci loop_ = nullptr; 87da853ecaSopenharmony_ci } 88da853ecaSopenharmony_ci } 89da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s stop exited", name_.data()); 90da853ecaSopenharmony_ci} 91da853ecaSopenharmony_ci 92da853ecaSopenharmony_civoid TaskThread::StopAsync() 93da853ecaSopenharmony_ci{ 94da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s StopAsync called", name_.data()); 95da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 96da853ecaSopenharmony_ci if (runningState_.load() != RunningState::STOPPING && runningState_.load() != RunningState::STOPPED) { 97da853ecaSopenharmony_ci runningState_ = RunningState::STOPPING; 98da853ecaSopenharmony_ci syncCond_.notify_all(); 99da853ecaSopenharmony_ci } 100da853ecaSopenharmony_ci} 101da853ecaSopenharmony_ci 102da853ecaSopenharmony_civoid TaskThread::Pause() 103da853ecaSopenharmony_ci{ 104da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s Pause called", name_.data()); 105da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 106da853ecaSopenharmony_ci switch (runningState_.load()) { 107da853ecaSopenharmony_ci case RunningState::STARTED: { 108da853ecaSopenharmony_ci runningState_ = RunningState::PAUSING; 109da853ecaSopenharmony_ci syncCond_.wait(lock, [this] { 110da853ecaSopenharmony_ci return runningState_.load() == RunningState::PAUSED || runningState_.load() == RunningState::STOPPED; 111da853ecaSopenharmony_ci }); 112da853ecaSopenharmony_ci break; 113da853ecaSopenharmony_ci } 114da853ecaSopenharmony_ci case RunningState::STOPPING: { 115da853ecaSopenharmony_ci syncCond_.wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; }); 116da853ecaSopenharmony_ci break; 117da853ecaSopenharmony_ci } 118da853ecaSopenharmony_ci case RunningState::PAUSING: { 119da853ecaSopenharmony_ci syncCond_.wait(lock, [this] { return runningState_.load() == RunningState::PAUSED; }); 120da853ecaSopenharmony_ci break; 121da853ecaSopenharmony_ci } 122da853ecaSopenharmony_ci default: 123da853ecaSopenharmony_ci break; 124da853ecaSopenharmony_ci } 125da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s Pause done.", name_.data()); 126da853ecaSopenharmony_ci} 127da853ecaSopenharmony_ci 128da853ecaSopenharmony_civoid TaskThread::PauseAsync() 129da853ecaSopenharmony_ci{ 130da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s PauseAsync called", name_.data()); 131da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 132da853ecaSopenharmony_ci if (runningState_.load() == RunningState::STARTED) { 133da853ecaSopenharmony_ci runningState_ = RunningState::PAUSING; 134da853ecaSopenharmony_ci } 135da853ecaSopenharmony_ci} 136da853ecaSopenharmony_ci 137da853ecaSopenharmony_civoid TaskThread::RegisterHandler(std::function<void()> handler) 138da853ecaSopenharmony_ci{ 139da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s RegisterHandler called", name_.data()); 140da853ecaSopenharmony_ci handler_ = std::move(handler); 141da853ecaSopenharmony_ci} 142da853ecaSopenharmony_ci 143da853ecaSopenharmony_civoid TaskThread::doTask() 144da853ecaSopenharmony_ci{ 145da853ecaSopenharmony_ci AVCODEC_LOGD("task %{public}s not override DoTask...", name_.data()); 146da853ecaSopenharmony_ci} 147da853ecaSopenharmony_ci 148da853ecaSopenharmony_civoid TaskThread::Run() 149da853ecaSopenharmony_ci{ 150da853ecaSopenharmony_ci // The max length for a thread name is 16. 151da853ecaSopenharmony_ci auto ret = pthread_setname_np(pthread_self(), name_.data()); 152da853ecaSopenharmony_ci if (ret != 0) { 153da853ecaSopenharmony_ci AVCODEC_LOGE("task %{public}s set name failed", name_.data()); 154da853ecaSopenharmony_ci } 155da853ecaSopenharmony_ci for (;;) { 156da853ecaSopenharmony_ci AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "task %{public}s is running on state : %{public}d", 157da853ecaSopenharmony_ci name_.data(), runningState_.load()); 158da853ecaSopenharmony_ci if (runningState_.load() == RunningState::STARTED) { 159da853ecaSopenharmony_ci handler_(); 160da853ecaSopenharmony_ci } 161da853ecaSopenharmony_ci std::unique_lock lock(stateMutex_); 162da853ecaSopenharmony_ci if (runningState_.load() == RunningState::PAUSING || runningState_.load() == RunningState::PAUSED) { 163da853ecaSopenharmony_ci runningState_ = RunningState::PAUSED; 164da853ecaSopenharmony_ci syncCond_.notify_all(); 165da853ecaSopenharmony_ci constexpr int timeoutMs = 500; 166da853ecaSopenharmony_ci syncCond_.wait_for(lock, std::chrono::milliseconds(timeoutMs), 167da853ecaSopenharmony_ci [this] { return runningState_.load() != RunningState::PAUSED; }); 168da853ecaSopenharmony_ci } 169da853ecaSopenharmony_ci if (runningState_.load() == RunningState::STOPPING || runningState_.load() == RunningState::STOPPED) { 170da853ecaSopenharmony_ci runningState_ = RunningState::STOPPED; 171da853ecaSopenharmony_ci syncCond_.notify_all(); 172da853ecaSopenharmony_ci break; 173da853ecaSopenharmony_ci } 174da853ecaSopenharmony_ci } 175da853ecaSopenharmony_ci} 176da853ecaSopenharmony_ci} // namespace MediaAVCodec 177da853ecaSopenharmony_ci} // namespace OHOS