1/* 2 * Copyright (c) 2021-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#define HST_LOG_TAG "Task" 17 18#include "osal/task/task.h" 19#include "common/log.h" 20 21namespace { 22constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Task" }; 23} 24 25namespace OHOS { 26namespace Media { 27// ffrt::qos priority sorting:qos_utility < qos_default < qos_user_initiated < 28// qos_deadline_request < qos_user_interactive 29ffrt::qos ConvertPriorityType(TaskPriority priority) 30{ 31 switch (priority) { 32 case TaskPriority::LOW: 33 return ffrt::qos_utility; 34 case TaskPriority::NORMAL: 35 return ffrt::qos_default; 36 case TaskPriority::MIDDLE: 37 return ffrt::qos_user_initiated; 38 case TaskPriority::HIGHEST: 39 return ffrt::qos_user_interactive; 40 default: 41 return ffrt::qos_deadline_request; 42 } 43} 44 45Task::Task(std::string name, TaskPriority priority) 46 : name_(std::move(name)), priority_(priority), runningState_(RunningState::STOPPED) 47{ 48 MEDIA_LOG_I("task " PUBLIC_LOG_S " ctor called", name_.c_str()); 49} 50 51Task::Task(std::string name, std::function<void()> job, TaskPriority priority) 52 : Task(std::move(name), priority) 53{ 54 MEDIA_LOG_I("task " PUBLIC_LOG_S " ctor called", name_.c_str()); 55 job_ = std::move(job); 56} 57 58Task::~Task() 59{ 60 MEDIA_LOG_I("task " PUBLIC_LOG_S " dtor called", name_.c_str()); 61 runningState_ = RunningState::STOPPED; 62 syncCond_.NotifyAll(); 63} 64 65void Task::Start() 66{ 67 MEDIA_LOG_I("task " PUBLIC_LOG_S " start called", name_.c_str()); 68 AutoLock lock(stateMutex_); 69 runningState_ = RunningState::STARTED; 70 if (!loop_) { 71 loop_ = std::make_unique<ffrt::thread>(name_.c_str(), ConvertPriorityType(priority_), [this] { Run(); }); 72 } 73 if (!loop_) { 74 MEDIA_LOG_E("task " PUBLIC_LOG_S " create failed", name_.c_str()); 75 } else { 76 syncCond_.NotifyAll(); 77 } 78} 79 80void Task::Stop() 81{ 82 MEDIA_LOG_W("task " PUBLIC_LOG_S " stop entered, current state: " PUBLIC_LOG_D32, 83 name_.c_str(), runningState_.load()); 84 AutoLock lock(stateMutex_); 85 if (runningState_.load() != RunningState::STOPPED) { 86 runningState_ = RunningState::STOPPING; 87 syncCond_.NotifyAll(); 88 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; }); 89 if (loop_) { 90 if (loop_->joinable()) { 91 loop_->join(); 92 } 93 loop_ = nullptr; 94 } 95 } 96 MEDIA_LOG_W("task " PUBLIC_LOG_S " stop exited", name_.c_str()); 97} 98 99void Task::StopAsync() 100{ 101 MEDIA_LOG_D("task " PUBLIC_LOG_S " StopAsync called", name_.c_str()); 102 AutoLock lock(stateMutex_); 103 if (runningState_.load() != RunningState::STOPPED) { 104 runningState_ = RunningState::STOPPING; 105 } 106} 107 108void Task::Pause() 109{ 110 AutoLock lock(stateMutex_); 111 RunningState state = runningState_.load(); 112 MEDIA_LOG_I("task " PUBLIC_LOG_S " Pause called, running state = " PUBLIC_LOG_D32, name_.c_str(), state); 113 switch (state) { 114 case RunningState::STARTED: { 115 runningState_ = RunningState::PAUSING; 116 syncCond_.Wait(lock, [this] { 117 return runningState_.load() == RunningState::PAUSED || runningState_.load() == RunningState::STOPPED; 118 }); 119 break; 120 } 121 case RunningState::STOPPING: { 122 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; }); 123 break; 124 } 125 case RunningState::PAUSING: { 126 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::PAUSED; }); 127 break; 128 } 129 default: 130 break; 131 } 132 MEDIA_LOG_I("task " PUBLIC_LOG_S " Pause done.", name_.c_str()); 133} 134 135void Task::PauseAsync() 136{ 137 MEDIA_LOG_I("task " PUBLIC_LOG_S " PauseAsync called", name_.c_str()); 138 AutoLock lock(stateMutex_); 139 if (runningState_.load() == RunningState::STARTED) { 140 runningState_ = RunningState::PAUSING; 141 } 142} 143 144void Task::RegisterJob(std::function<void()> job) 145{ 146 MEDIA_LOG_D("task " PUBLIC_LOG_S " RegisterJob called", name_.c_str()); 147 job_ = std::move(job); 148} 149 150void Task::DoTask() 151{ 152 MEDIA_LOG_D("task " PUBLIC_LOG_S " not override DoTask...", name_.c_str()); 153} 154 155void Task::Run() 156{ 157 for (;;) { 158 MEDIA_LOG_DD("task " PUBLIC_LOG_S " is running on state : " PUBLIC_LOG_D32, 159 name_.c_str(), runningState_.load()); 160 if (runningState_.load() == RunningState::STARTED) { 161 job_(); 162 } 163 AutoLock lock(stateMutex_); 164 if (runningState_.load() == RunningState::PAUSING || runningState_.load() == RunningState::PAUSED) { 165 runningState_ = RunningState::PAUSED; 166 syncCond_.NotifyAll(); 167 constexpr int timeoutMs = 500; 168 syncCond_.WaitFor(lock, timeoutMs, [this] { return runningState_.load() != RunningState::PAUSED; }); 169 } 170 if (runningState_.load() == RunningState::STOPPING || runningState_.load() == RunningState::STOPPED) { 171 MEDIA_LOG_I("task " PUBLIC_LOG_S " is stopped", name_.c_str()); 172 runningState_ = RunningState::STOPPED; 173 syncCond_.NotifyAll(); 174 break; 175 } 176 } 177} 178} // namespace Media 179} // namespace OHOS 180