• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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