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 "inner_api/common/log.h"
20
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Task" };
23 }
24
25 namespace OHOS {
26 namespace Media {
27 // ffrt::qos priority sorting:qos_utility < qos_default < qos_user_initiated <
28 // qos_deadline_request < qos_user_interactive
ConvertPriorityType(TaskPriority priority)29 ffrt::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
Task(std::string name,TaskPriority priority)45 Task::Task(std::string name, TaskPriority priority)
46 : name_(std::move(name)), priority_(priority), runningState_(RunningState::STOPPED)
47 {
48 MEDIA_LOG_D("task " PUBLIC_LOG_S " ctor called", name_.c_str());
49 }
50
Task(std::string name,std::function<void ()> job,TaskPriority priority)51 Task::Task(std::string name, std::function<void()> job, TaskPriority priority)
52 : Task(std::move(name), priority)
53 {
54 MEDIA_LOG_D("task " PUBLIC_LOG_S " ctor called", name_.c_str());
55 job_ = std::move(job);
56 }
57
~Task()58 Task::~Task()
59 {
60 MEDIA_LOG_I("task " PUBLIC_LOG_S " dtor called", name_.c_str());
61 runningState_ = RunningState::STOPPED;
62 syncCond_.NotifyAll();
63 }
64
Start()65 void 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
Stop()80 void 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
StopAsync()99 void 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
Pause()108 void 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
PauseAsync()135 void 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
RegisterJob(std::function<void ()> job)144 void 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
DoTask()150 void Task::DoTask()
151 {
152 MEDIA_LOG_D("task " PUBLIC_LOG_S " not override DoTask...", name_.c_str());
153 }
154
Run()155 void 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