1 /*
2  * Copyright (c) 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 #include "task_handler_wrap.h"
17 
18 #include <cinttypes>
19 #include <mutex>
20 #include "cpp/mutex.h"
21 #include "hilog_tag_wrapper.h"
22 #include "ffrt_task_utils_wrap.h"
23 #include "queue_task_handler_wrap.h"
24 #include "ffrt_task_handler_wrap.h"
25 
26 namespace OHOS {
27 namespace AAFwk {
28 constexpr int MILL_TO_MICRO = 1000;
Cancel() const29 bool TaskHandle::Cancel() const
30 {
31     auto handler = handler_.lock();
32     if (!status_ || !handler || !innerTaskHandle_) {
33         return false;
34     }
35 
36     auto &status = *status_;
37     if (status != TaskStatus::PENDING) {
38         return false;
39     }
40 
41     auto ret = handler->CancelTaskInner(innerTaskHandle_);
42     // Here the result is ignored and status is set to canceled
43     status = TaskStatus::CANCELED;
44     return ret;
45 }
Sync() const46 void TaskHandle::Sync() const
47 {
48     auto handler = handler_.lock();
49     if (!status_ || !handler || !innerTaskHandle_) {
50         TAG_LOGI(AAFwkTag::DEFAULT, "Invalid status");
51         return;
52     }
53     auto &status = *status_;
54     if (status == TaskStatus::FINISHED || status == TaskStatus::CANCELED) {
55         TAG_LOGI(AAFwkTag::DEFAULT, "Invalid status");
56         return;
57     }
58     handler->WaitTaskInner(innerTaskHandle_);
59 }
60 
61 std::atomic_int32_t TaskHandlerWrap::g_taskId = 0;
62 
CreateQueueHandler(const std::string & queueName,TaskQoS queueQos)63 std::shared_ptr<TaskHandlerWrap> TaskHandlerWrap::CreateQueueHandler(const std::string &queueName,
64     TaskQoS queueQos)
65 {
66     return std::make_shared<QueueTaskHandlerWrap>(queueName, queueQos);
67 }
68 
GetFfrtHandler()69 std::shared_ptr<TaskHandlerWrap> TaskHandlerWrap::GetFfrtHandler()
70 {
71     static auto ffrtHandler = std::make_shared<FfrtTaskHandlerWrap>();
72     return ffrtHandler;
73 }
74 
TaskHandlerWrap(const std::string & queueName)75 TaskHandlerWrap::TaskHandlerWrap(const std::string &queueName) : queueName_(queueName)
76 {
77     tasksMutex_ = std::make_unique<ffrt::mutex>();
78 }
79 
80 TaskHandlerWrap::~TaskHandlerWrap() = default;
81 
SubmitTask(const std::function<void ()> & task)82 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task)
83 {
84     return SubmitTask(task, TaskAttribute());
85 }
SubmitTask(const std::function<void ()> & task,const std::string & name)86 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task, const std::string &name)
87 {
88     return SubmitTask(task, TaskAttribute{name});
89 }
SubmitTask(const std::function<void ()> & task,int64_t delayMillis)90 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task, int64_t delayMillis)
91 {
92     return SubmitTask(task, TaskAttribute{.delayMillis_ = delayMillis});
93 }
SubmitTask(const std::function<void ()> & task,TaskQoS taskQos)94 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task, TaskQoS taskQos)
95 {
96     return SubmitTask(task, TaskAttribute{.taskQos_ = taskQos});
97 }
SubmitTaskJust(const std::function<void ()> & task,const std::string & name,int64_t delayMillis)98 TaskHandle TaskHandlerWrap::SubmitTaskJust(const std::function<void()> &task,
99     const std::string &name, int64_t delayMillis)
100 {
101     return SubmitTask(task, TaskAttribute{name, delayMillis});
102 }
SubmitTask(const std::function<void ()> & task,const std::string & name,int64_t delayMillis,bool forceSubmit)103 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task,
104     const std::string &name, int64_t delayMillis, bool forceSubmit)
105 {
106     TaskAttribute taskAttr{name, delayMillis};
107     std::lock_guard<ffrt::mutex> guard(*tasksMutex_);
108     auto it = tasks_.find(name);
109     if (it != tasks_.end()) {
110         TAG_LOGD(AAFwkTag::DEFAULT, "SubmitTask repeated task: %{public}s", name.c_str());
111         if (forceSubmit) {
112             return SubmitTask(task, taskAttr);
113         } else {
114             return TaskHandle();
115         }
116     }
117 
118     auto result = SubmitTask(task, taskAttr);
119     tasks_.emplace(name, result);
120 
121     // submit clear task to clear map record
122     auto clearTask = [whandler = weak_from_this(), name, taskHandle = result]() {
123         auto handler = whandler.lock();
124         if (!handler) {
125             return;
126         }
127         handler->RemoveTask(name, taskHandle);
128     };
129     SubmitTask(clearTask, delayMillis);
130 
131     return result;
132 }
133 
SubmitTask(const std::function<void ()> & task,const TaskAttribute & taskAttr)134 TaskHandle TaskHandlerWrap::SubmitTask(const std::function<void()> &task, const TaskAttribute &taskAttr)
135 {
136     if (!task) {
137         return TaskHandle();
138     }
139 
140     TaskHandle result(shared_from_this(), nullptr);
141     result.taskId_ = ++g_taskId;
142     result.printTaskLog_ = printTaskLog_;
143     auto taskWrap = [result, task, taskName = taskAttr.taskName_]() {
144         if (result.PrintTaskLog()) {
145             TAG_LOGW(AAFwkTag::DEFAULT, "begin execute task name: %{public}s, taskId: %{public}d",
146                 taskName.c_str(), result.GetTaskId());
147         }
148         *result.status_ = TaskStatus::EXECUTING;
149         task();
150         *result.status_ = TaskStatus::FINISHED;
151     };
152 
153     if (printTaskLog_) {
154         TAG_LOGW(AAFwkTag::DEFAULT, "submitTask: %{public}s, taskId: %{public}d, queueName: %{public}s count: "
155             "%{public}" PRIu64"", taskAttr.taskName_.c_str(), result.taskId_, queueName_.c_str(), GetTaskCount());
156     }
157     result.innerTaskHandle_ = SubmitTaskInner(std::move(taskWrap), taskAttr);
158     return result;
159 }
160 
CancelTask(const std::string & name)161 bool TaskHandlerWrap::CancelTask(const std::string &name)
162 {
163     TAG_LOGD(AAFwkTag::DEFAULT, "CancelTask task: %{public}s", name.c_str());
164     std::lock_guard<ffrt::mutex> guard(*tasksMutex_);
165     auto it = tasks_.find(name);
166     if (it == tasks_.end()) {
167         return false;
168     }
169 
170     auto taskHandle = it->second;
171     tasks_.erase(it);
172     if (printTaskLog_) {
173         TAG_LOGW(AAFwkTag::DEFAULT, "cancel task name: %{public}s, taskId: %{public}d, queueName: %{public}s",
174             name.c_str(), taskHandle.taskId_, queueName_.c_str());
175     }
176     return taskHandle.Cancel();
177 }
178 
RemoveTask(const std::string & name,const TaskHandle & taskHandle)179 bool TaskHandlerWrap::RemoveTask(const std::string &name, const TaskHandle &taskHandle)
180 {
181     std::lock_guard<ffrt::mutex> guard(*tasksMutex_);
182     auto it = tasks_.find(name);
183     if (it == tasks_.end() || !it->second.IsSame(taskHandle)) {
184         return false;
185     }
186     tasks_.erase(it);
187     return true;
188 }
189 
Convert2FfrtQos(TaskQoS taskqos)190 ffrt::qos Convert2FfrtQos(TaskQoS taskqos)
191 {
192     switch (taskqos) {
193         case TaskQoS::INHERENT:
194             return ffrt::qos_inherit;
195         case TaskQoS::BACKGROUND:
196             return ffrt::qos_background;
197         case TaskQoS::UTILITY:
198             return ffrt::qos_utility;
199         case TaskQoS::DEFAULT:
200             return ffrt::qos_default;
201         case TaskQoS::USER_INITIATED:
202             return ffrt::qos_user_initiated;
203         case TaskQoS::DEADLINE_REQUEST:
204             return ffrt::qos_deadline_request;
205         case TaskQoS::USER_INTERACTIVE:
206             return ffrt::qos_user_interactive;
207         default:
208             break;
209     }
210 
211     return ffrt::qos_inherit;
212 }
BuildFfrtTaskAttr(const TaskAttribute & taskAttr,ffrt::task_attr & result)213 void BuildFfrtTaskAttr(const TaskAttribute &taskAttr, ffrt::task_attr &result)
214 {
215     if (taskAttr.delayMillis_ > 0) {
216         result.delay(taskAttr.delayMillis_ * MILL_TO_MICRO);
217     }
218     if (!taskAttr.taskName_.empty()) {
219         result.name(taskAttr.taskName_.c_str());
220     }
221     if (taskAttr.taskQos_ != TaskQoS::DEFAULT) {
222         result.qos(Convert2FfrtQos(taskAttr.taskQos_));
223     }
224     if (taskAttr.timeout_ > 0) {
225         result.timeout(taskAttr.timeout_);
226     }
227 }
228 }  // namespace AAFWK
229 }  // namespace OHOS