1 /*
2 * Copyright (c) 2021-2022 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 #include "task.h"
16 #include "hilog_wrapper.h"
17 namespace OHOS {
18 namespace AppExecFwk {
19 /**
20 * @brief Constructs the object.
21 * @param runnable The user task wrapped in.
22 * @param priority The priority
23 * @return None
24 */
Task(const std::shared_ptr<Runnable> & runnable,const TaskPriority priority,const std::shared_ptr<BaseTaskDispatcher> & baseTaskDispatcher)25 Task::Task(const std::shared_ptr<Runnable> &runnable, const TaskPriority priority,
26 const std::shared_ptr<BaseTaskDispatcher> &baseTaskDispatcher)
27 : taskListeners_()
28 {
29 runnable_ = runnable;
30 priority_ = priority;
31 baseTaskDispatcher_ = baseTaskDispatcher;
32 std::atomic_init(&state_, 0U);
33 HILOG_INFO("Task::Task init listener count=%{public}zu", taskListeners_.Size());
34 }
~Task()35 Task::~Task()
36 {}
37
38 /**
39 * @brief invoke the function to execute the task
40 * @param None
41 * @return None
42 */
Run()43 void Task::Run()
44 {
45 HILOG_INFO("Task::Run task run called start");
46 if (runnable_ == nullptr) {
47 HILOG_INFO("Task::Run called runnable_ is null");
48 return;
49 }
50 // Task cannot be reused.
51 if (EnterExecute()) {
52 HILOG_INFO("Task::Run runnable_ Run called start");
53 (*runnable_.get())();
54 }
55 HILOG_INFO("Task::Run runnable_ Run called end");
56 }
57
58 /**
59 * @brief Gets the priority.
60 * @param None
61 * @return The priority.
62 */
GetPriority() const63 TaskPriority Task::GetPriority() const
64 {
65 return priority_;
66 }
67
68 /**
69 * @brief Sets the sequence.
70 * @param None
71 * @param sequence The sequence
72 * @return None
73 */
SetSequence(long sequence)74 void Task::SetSequence(long sequence)
75 {
76 sequence_ = sequence;
77 }
78
79 /**
80 * @brief Gets the sequence.
81 * @param None
82 * @return The sequence.
83 */
GetSequence() const84 long Task::GetSequence() const
85 {
86 return sequence_;
87 }
88
89 /**
90 * @brief Revoke this task if hasn't run.
91 * @param None
92 * @return true if set revoked or already revoked. False if the task has start executing.
93 */
Revoke()94 bool Task::Revoke()
95 {
96 if (runnable_ == nullptr) {
97 HILOG_ERROR("Task.Revoke called runnable_ is null");
98 return false;
99 }
100 RevokeResult result = SetRevoked();
101 HILOG_INFO("Task.Revoke result: %{public}u", result);
102 if (result == SUCCESS) {
103 OnTaskCanceled();
104 }
105 return (result == SUCCESS) || (result == ALREADY_REVOKED);
106 }
107
108 /**
109 * @brief Adds a task listener.
110 * @param listener The listener
111 * @return None
112 */
AddTaskListener(const std::shared_ptr<TaskListener> & listener)113 void Task::AddTaskListener(const std::shared_ptr<TaskListener> &listener)
114 {
115 HILOG_INFO("Task.AddTaskListener listener called start");
116 taskListeners_.Offer(listener);
117 }
118
119 /**
120 * @brief Called when task is about to run.
121 * @param None
122 * @return None
123 */
BeforeTaskExecute()124 void Task::BeforeTaskExecute()
125 {
126 if ((state_ & REVOKED) != REVOKED) {
127 ConcurrentQueueStatusUpdate(TaskStage::BEFORE_EXECUTE);
128 }
129 }
130
131 /**
132 * @brief Called when task is done.
133 * @param None
134 * @return None
135 */
AfterTaskExecute()136 void Task::AfterTaskExecute()
137 {
138 if ((state_ & EXECUTED) == EXECUTED) {
139 HILOG_INFO("Task.AfterTaskExecute taskStage called AFTER_EXECUTE");
140 ConcurrentQueueStatusUpdate(TaskStage::AFTER_EXECUTE);
141 }
142 }
143
144 /**
145 * @brief Called when task is canceled.
146 * @param None
147 * @return None
148 */
OnTaskCanceled()149 void Task::OnTaskCanceled()
150 {
151 HILOG_INFO("Task.OnTaskCanceled taskStage called REVOKED");
152 ConcurrentQueueStatusUpdate(TaskStage::REVOKED);
153 }
154
155 /**
156 * @brief Return true if not executed or revoked, and if not executed or revoked, ensure |EXECUTED| to be set.
157 * @param None
158 * @return bool
159 */
EnterExecute()160 bool Task::EnterExecute()
161 {
162 unsigned int stateNotIn = EXECUTED | REVOKED;
163 while (true) {
164 unsigned int value = state_.load();
165 if ((state_ & stateNotIn) == 0) {
166 // Not executed or revoked
167 if (state_.compare_exchange_strong(value, EXECUTED)) {
168 HILOG_INFO("Task.EnterExecute return success");
169 return true;
170 }
171 } else {
172 HILOG_ERROR("Task.EnterExecute return fail, state=%{public}d, stateNotIn=%{public}d", value, stateNotIn);
173 return false;
174 }
175 }
176 }
177
SetRevoked()178 Task::RevokeResult Task::SetRevoked()
179 {
180 while (true) {
181 unsigned int value = state_.load();
182 if ((value & REVOKED) == REVOKED) {
183 HILOG_WARN("Task.SetRevoked return ALREADY_REVOKED");
184 return ALREADY_REVOKED;
185 }
186 if ((value & EXECUTED) == 0) {
187 if (state_.compare_exchange_strong(value, REVOKED)) {
188 HILOG_INFO("Task.SetRevoked return SUCCESS");
189 return SUCCESS;
190 }
191 } else {
192 HILOG_ERROR("Task.SetRevoked return FAIL");
193 return FAIL;
194 }
195 }
196 }
197
ConcurrentQueueStatusUpdate(const TaskStage::TASKSTAGE taskstage)198 void Task::ConcurrentQueueStatusUpdate(const TaskStage::TASKSTAGE taskstage)
199 {
200 HILOG_INFO("Task.ConcurrentQueueStatusUpdate taskListeners_ called start");
201 for (auto iter = taskListeners_.Begin(); iter != taskListeners_.End(); iter++) {
202 (*iter)->OnChanged(taskstage);
203 }
204 if (taskstage == TaskStage::TASKSTAGE::AFTER_EXECUTE) {
205 taskListeners_.clear();
206 }
207 }
208
operator ==(std::shared_ptr<Task> & rec) const209 bool Task::operator==(std::shared_ptr<Task> &rec) const
210 {
211 return ((this->sequence_ == rec->sequence_) && (this->state_ == rec->state_) &&
212 (this->priority_ == rec->priority_) &&
213 (this->revocable_ == rec->revocable_) && (this->runnable_ == rec->runnable_) &&
214 (this->baseTaskDispatcher_ == rec->baseTaskDispatcher_));
215 }
216 } // namespace AppExecFwk
217 } // namespace OHOS
218