1 /*
2 * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "Task"
16
17 #include "foundation/osal/thread/task.h"
18 #include "foundation/cpp_ext/memory_ext.h"
19 #include "foundation/log.h"
20
21 namespace OHOS {
22 namespace Media {
23 namespace OSAL {
Task(std::string name,ThreadPriority priority)24 Task::Task(std::string name, ThreadPriority priority)
25 : name_(std::move(name)), priority_(priority), runningState_(RunningState::STOPPED)
26 {
27 MEDIA_LOG_D("task " PUBLIC_LOG_S " ctor called", name_.c_str());
28 loop_ = CppExt::make_unique<OSAL::Thread>(priority);
29 loop_->SetName(name_);
30 }
31
Task(std::string name,std::function<void ()> handler,ThreadPriority priority)32 Task::Task(std::string name, std::function<void()> handler, ThreadPriority priority)
33 : Task(std::move(name), priority)
34 {
35 MEDIA_LOG_D("task " PUBLIC_LOG_S " ctor called", name_.c_str());
36 handler_ = std::move(handler);
37 }
38
~Task()39 Task::~Task()
40 {
41 MEDIA_LOG_I("task " PUBLIC_LOG_S " dtor called", name_.c_str());
42 runningState_ = RunningState::STOPPED;
43 syncCond_.NotifyAll();
44 }
45
Start()46 void Task::Start()
47 {
48 #ifndef START_FAKE_TASK
49 MEDIA_LOG_I("task " PUBLIC_LOG_S " start called", name_.c_str());
50 OSAL::ScopedLock lock(stateMutex_);
51 runningState_ = RunningState::STARTED;
52 if (!loop_) { // thread not exist
53 loop_ = CppExt::make_unique<OSAL::Thread>(priority_);
54 }
55 if (!loop_->HasThread() && !loop_->CreateThread([this] { Run(); })) {
56 MEDIA_LOG_E("task " PUBLIC_LOG_S " create failed", name_.c_str());
57 } else {
58 syncCond_.NotifyAll();
59 }
60 #endif
61 }
62
Stop()63 void Task::Stop()
64 {
65 MEDIA_LOG_W("task " PUBLIC_LOG_S " stop entered, current state: " PUBLIC_LOG_D32,
66 name_.c_str(), runningState_.load());
67 OSAL::ScopedLock lock(stateMutex_);
68 if (runningState_.load() != RunningState::STOPPED) {
69 runningState_ = RunningState::STOPPING;
70 syncCond_.NotifyAll();
71 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; });
72 if (loop_ && loop_->HasThread()) {
73 loop_ = nullptr;
74 }
75 }
76 MEDIA_LOG_W("task " PUBLIC_LOG_S " stop exited", name_.c_str());
77 }
78
StopAsync()79 void Task::StopAsync()
80 {
81 MEDIA_LOG_D("task " PUBLIC_LOG_S " StopAsync called", name_.c_str());
82 OSAL::ScopedLock lock(stateMutex_);
83 if (runningState_.load() != RunningState::STOPPED) {
84 runningState_ = RunningState::STOPPING;
85 }
86 }
87
Pause()88 void Task::Pause()
89 {
90 OSAL::ScopedLock lock(stateMutex_);
91 RunningState state = runningState_.load();
92 MEDIA_LOG_I("task " PUBLIC_LOG_S " Pause called, running state = " PUBLIC_LOG_D32, name_.c_str(), state);
93 switch (state) {
94 case RunningState::STARTED: {
95 runningState_ = RunningState::PAUSING;
96 syncCond_.Wait(lock, [this] {
97 return runningState_.load() == RunningState::PAUSED || runningState_.load() == RunningState::STOPPED;
98 });
99 break;
100 }
101 case RunningState::STOPPING: {
102 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::STOPPED; });
103 break;
104 }
105 case RunningState::PAUSING: {
106 syncCond_.Wait(lock, [this] { return runningState_.load() == RunningState::PAUSED; });
107 break;
108 }
109 default:
110 break;
111 }
112 MEDIA_LOG_I("task " PUBLIC_LOG_S " Pause done.", name_.c_str());
113 }
114
PauseAsync()115 void Task::PauseAsync()
116 {
117 MEDIA_LOG_I("task " PUBLIC_LOG_S " PauseAsync called", name_.c_str());
118 OSAL::ScopedLock lock(stateMutex_);
119 if (runningState_.load() == RunningState::STARTED) {
120 runningState_ = RunningState::PAUSING;
121 }
122 }
123
RegisterHandler(std::function<void ()> handler)124 void Task::RegisterHandler(std::function<void()> handler)
125 {
126 MEDIA_LOG_D("task " PUBLIC_LOG_S " RegisterHandler called", name_.c_str());
127 handler_ = std::move(handler);
128 }
129
DoTask()130 void Task::DoTask()
131 {
132 MEDIA_LOG_D("task " PUBLIC_LOG_S " not override DoTask...", name_.c_str());
133 }
134
Run()135 void Task::Run()
136 {
137 for (;;) {
138 MEDIA_LOG_DD("task " PUBLIC_LOG_S " is running on state : " PUBLIC_LOG_D32,
139 name_.c_str(), runningState_.load());
140 if (runningState_.load() == RunningState::STARTED) {
141 handler_();
142 }
143 OSAL::ScopedLock lock(stateMutex_);
144 if (runningState_.load() == RunningState::PAUSING || runningState_.load() == RunningState::PAUSED) {
145 runningState_ = RunningState::PAUSED;
146 syncCond_.NotifyAll();
147 constexpr int timeoutMs = 500;
148 syncCond_.WaitFor(lock, timeoutMs, [this] { return runningState_.load() != RunningState::PAUSED; });
149 }
150 if (runningState_.load() == RunningState::STOPPING || runningState_.load() == RunningState::STOPPED) {
151 MEDIA_LOG_I("task " PUBLIC_LOG_S " is stopped", name_.c_str());
152 runningState_ = RunningState::STOPPED;
153 syncCond_.NotifyAll();
154 break;
155 }
156 }
157 }
158 } // namespace OSAL
159 } // namespace Media
160 } // namespace OHOS
161