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