• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H
18 
19 #include <cstdint>
20 #include <functional>
21 
22 #include "base/memory/ace_type.h"
23 #include "base/thread/cancelable_callback.h"
24 #include "base/utils/noncopyable.h"
25 #include "base/log/log.h"
26 
27 #ifndef __has_builtin
28 #define __has_builtin(x) 0
29 #endif
30 
31 namespace OHOS::Ace {
32 struct Caller final {
33 #if __has_builtin(__builtin_FILE)
34     Caller(std::string file = __builtin_FILE(), int line = __builtin_LINE(), std::string func = __builtin_FUNCTION())
file_final35         : file_(file), line_(line), func_(func)
36     {
37         if (!file_.empty()) {
38             size_t split = file_.find_last_of("/\\");
39             if (split == std::string::npos) {
40                 split = 0;
41             }
42             caller_ = std::string("[" + file_.substr(split + 1) + "(" + func_ + ":" + std::to_string(line_) + ")]");
43         }
44     }
45 #else
46     Caller() {
47     }
48 #endif
49 
50     std::string file_;
51     int32_t line_ = 0;
52     std::string func_;
53     std::string caller_ = "[]";
54 };
55 
56 class TaskExecutor : public AceType {
57     DECLARE_ACE_TYPE(TaskExecutor, AceType);
58     ACE_DISALLOW_COPY_AND_MOVE(TaskExecutor);
59 
60 public:
61     using Task = std::function<void()>;
62     using CancelableTask = CancelableCallback<void()>;
63 
64     static constexpr int32_t TASK_TYPE_SIZE = 7;
65     enum class TaskType : uint32_t {
66         PLATFORM = 0,
67         UI,
68         IO,
69         GPU,
70         JS,
71         BACKGROUND,
72         UNKNOWN,
73     };
74 
75     ~TaskExecutor() override = default;
76 
77     /**
78      * Post a task to the specified thread.
79      *
80      * @param task Task which need execution.
81      * @param type FrontendType of task, used to specify the thread.
82      * @return Returns 'true' whether task has been post successfully.
83      */
84     bool PostTask(Task&& task, TaskType type, const Caller& caller = {}) const
85     {
86         return PostDelayedTask(std::move(task), type, 0, caller);
87     }
88 
89     /**
90      * Post a task to the specified thread.
91      *
92      * @param task Task which need execution.
93      * @param type FrontendType of task, used to specify the thread.
94      * @return Returns 'true' if task has been posted successfully.
95      */
96     bool PostTask(const Task& task, TaskType type, const Caller& caller = {}) const
97     {
98         return PostDelayedTask(task, type, 0, caller);
99     }
100 
101     /**
102      * Post a task to the specified thread with a trace id.
103      *
104      * @param task Task which need execution.
105      * @param type FrontendType of task, used to specify the thread.
106      * @param id The id to trace the task.
107      * @return Returns 'true' whether task has been post successfully.
108      */
109     bool PostTaskWithTraceId(Task&& task, TaskType type, int32_t id, const Caller& caller = {}) const
110     {
111         Task wrappedTask = WrapTaskWithTraceId(std::move(task), id);
112         return PostDelayedTask(std::move(wrappedTask), type, 0, caller);
113     }
114 
115     /**
116      * Post a task to the specified thread.
117      *
118      * @param task Task which need execution.
119      * @param type FrontendType of task, used to specify the thread.
120      * @param id The id to trace the task.
121      * @return Returns 'true' if task has been posted successfully.
122      */
123     bool PostTaskWithTraceId(const Task& task, TaskType type, int32_t id, const Caller& caller = {}) const
124     {
125         Task wrappedTask = WrapTaskWithTraceId(Task(task), id);
126         return PostDelayedTask(std::move(wrappedTask), type, 0, caller);
127     }
128 
129     /**
130      * Post a delayed task to the specified thread.
131      * Never allow to post a background delayed task.
132      *
133      * @param task Task which need execution.
134      * @param type FrontendType of task, used to specify the thread.
135      * @param delayTime Wait a period of time in milliseconds before execution.
136      * @return Returns 'true' if task has been posted successfully.
137      */
138     bool PostDelayedTask(Task&& task, TaskType type, uint32_t delayTime, const Caller& caller = {}) const
139     {
140         if (delayTime > 0 && type == TaskType::BACKGROUND) {
141             return false;
142         }
143         return OnPostTask(std::move(task), type, delayTime, caller.caller_);
144     }
145 
146     /**
147      * Post a delayed task to the specified thread.
148      * Never allow to post a background delayed task.
149      *
150      * @param task Task which need execution.
151      * @param type FrontendType of task, used to specify the thread.
152      * @param delayTime Wait a period of time in milliseconds before execution.
153      * @return Returns 'true' if task has been posted successfully.
154      */
155     bool PostDelayedTask(const Task& task, TaskType type, uint32_t delayTime, const Caller& caller = {}) const
156     {
157         return PostDelayedTask(Task(task), type, delayTime, caller);
158     }
159 
160     /**
161      * Post a task to the specified thread and wait until finished executing.
162      * Never allow to post a background synchronous task.
163      *
164      * @param task Task which need execution.
165      * @param type FrontendType of task, used to specify the thread.
166      * @return Returns 'true' whether task has been executed.
167      */
168     bool PostSyncTask(Task&& task, TaskType type, const Caller& caller = {}) const
169     {
170         if (!task || type == TaskType::BACKGROUND) {
171             return false;
172         } else if (WillRunOnCurrentThread(type)) {
173             task();
174             return true;
175         }
176         return PostTaskAndWait(CancelableTask(std::move(task)), type, 0ms, caller.caller_);
177     }
178 
179     /**
180      * Post a task to the specified thread and wait until finished executing.
181      * Never allow to post a background synchronous task.
182      *
183      * @param task Task which need execution.
184      * @param type FrontendType of task, used to specify the thread.
185      * @param timeoutMs Timeout in milliseconds before task execution.
186      * @return Returns 'true' whether task has been executed.
187      */
188     bool PostSyncTaskTimeout(const Task& task, TaskType type, uint32_t timeoutMs, const Caller& caller = {}) const
189     {
190         if (!task || type == TaskType::BACKGROUND) {
191             return false;
192         } else if (WillRunOnCurrentThread(type)) {
193             task();
194             return true;
195         }
196         return PostTaskAndWait(
197             CancelableTask(std::move(task)), type, std::chrono::milliseconds(timeoutMs), caller.caller_);
198     }
199 
200     /**
201      * Post a task to the specified thread and wait until finished executing.
202      * Never allow to post a background synchronous task.
203      *
204      * @param task Task which need execution.
205      * @param type FrontendType of task, used to specify the thread.
206      * @return Returns 'true' whether task has been executed.
207      */
208     bool PostSyncTask(const Task& task, TaskType type, const Caller& caller = {}) const
209     {
210         return PostSyncTask(Task(task), type, caller);
211     }
212 
213     /**
214      * Post a cancelable task to the specified thread and wait until finished executing.
215      * Never allow to post a background synchronous task.
216      *
217      * @param task Task which need execution.
218      * @param type FrontendType of task, used to specify the thread.
219      * @return Returns 'true' whether task has been executed.
220      */
221     bool PostSyncTask(CancelableTask&& task, TaskType type, const Caller& caller = {}) const
222     {
223         if (!task || type == TaskType::BACKGROUND) {
224             return false;
225         } else if (WillRunOnCurrentThread(type)) {
226             CancelableTask avatar(task);
227             task();
228             return avatar.WaitUntilComplete();
229         }
230         return PostTaskAndWait(std::move(task), type, 0ms, caller.caller_);
231     }
232 
233     /**
234      * Post a cancelable task to the specified thread and wait until finished executing.
235      * Never allow to post a background synchronous task.
236      *
237      * @param task Task which need execution.
238      * @param type FrontendType of task, used to specify the thread.
239      * @return Returns 'true' whether task has been executed.
240      */
241     bool PostSyncTask(const CancelableTask& task, TaskType type, const Caller& caller = {}) const
242     {
243         return PostSyncTask(CancelableTask(task), type, caller);
244     }
245 
246     virtual void AddTaskObserver(Task&& callback) = 0;
247     virtual void RemoveTaskObserver() = 0;
248     virtual bool WillRunOnCurrentThread(TaskType type) const = 0;
249 
GetTid(TaskType type)250     virtual int32_t GetTid(TaskType type)
251     {
252         return 0;
253     }
254 
GetTotalTaskNum(TaskType type)255     virtual uint32_t GetTotalTaskNum(TaskType type)
256     {
257         return 0;
258     }
259 
260 protected:
261     TaskExecutor() = default;
262 
263     virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime, const std::string& callerInfo) const = 0;
264     virtual Task WrapTaskWithTraceId(Task&& task, int32_t id) const = 0;
265 
266 #ifdef ACE_DEBUG
OnPreSyncTask(TaskType type)267     virtual bool OnPreSyncTask(TaskType type) const
268     {
269         return true;
270     }
OnPostSyncTask()271     virtual void OnPostSyncTask() const {}
272 #endif
273 
274 private:
275     bool PostTaskAndWait(CancelableTask&& task, TaskType type, std::chrono::milliseconds timeoutMs = 0ms,
276         const std::string& callerInfo = {}) const
277     {
278 #ifdef ACE_DEBUG
279         bool result = false;
280         if (OnPreSyncTask(type)) {
281             result = OnPostTask(Task(task), type, 0, callerInfo) && task.WaitUntilComplete(timeoutMs);
282             OnPostSyncTask();
283         }
284         return result;
285 #else
286         return OnPostTask(Task(task), type, 0, callerInfo) && task.WaitUntilComplete(timeoutMs);
287 #endif
288     }
289 };
290 
291 class TaskWrapper {
292 public:
293     virtual bool WillRunOnCurrentThread() = 0;
294     virtual void Call(const TaskExecutor::Task& task) = 0;
295 
296     virtual ~TaskWrapper() = default;
297 };
298 
299 class SingleTaskExecutor final {
300 public:
301     using Task = TaskExecutor::Task;
302     using CancelableTask = TaskExecutor::CancelableTask;
303     using TaskType = TaskExecutor::TaskType;
304 
SingleTaskExecutor(RefPtr<TaskExecutor> && taskExecutor,TaskType type)305     SingleTaskExecutor(RefPtr<TaskExecutor>&& taskExecutor, TaskType type)
306         : taskExecutor_(std::move(taskExecutor)), type_(type)
307     {}
SingleTaskExecutor(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)308     SingleTaskExecutor(const RefPtr<TaskExecutor>& taskExecutor, TaskType type)
309         : taskExecutor_(taskExecutor), type_(type)
310     {}
311     ~SingleTaskExecutor() = default;
312 
Make(RefPtr<TaskExecutor> && taskExecutor,TaskType type)313     static SingleTaskExecutor Make(RefPtr<TaskExecutor>&& taskExecutor, TaskType type)
314     {
315         return SingleTaskExecutor(std::move(taskExecutor), type);
316     }
317 
Make(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)318     static SingleTaskExecutor Make(const RefPtr<TaskExecutor>& taskExecutor, TaskType type)
319     {
320         return SingleTaskExecutor(taskExecutor, type);
321     }
322 
323     /**
324      * Post a task to the specified thread.
325      *
326      * @param task Task which need execution.
327      * @return Returns 'true' whether task has been post successfully.
328      */
329     bool PostTask(Task&& task, const Caller& caller = {}) const
330     {
331         return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_, caller) : false;
332     }
333 
334     /**
335      * Post a task to the specified thread.
336      *
337      * @param task Task which need execution.
338      * @return Returns 'true' whether task has been post successfully.
339      */
340     bool PostTask(const Task& task, const Caller& caller = {}) const
341     {
342         return taskExecutor_ ? taskExecutor_->PostTask(task, type_, caller) : false;
343     }
344 
345     /**
346      * Post a delayed task to the specified thread.
347      * Never allow to post a background delayed task.
348      *
349      * @param task Task which need execution.
350      * @param delayTime Wait a period of time in milliseconds before execution.
351      * @return Returns 'true' if task has been posted successfully.
352      */
353     bool PostDelayedTask(Task&& task, uint32_t delayTime, const Caller& caller = {}) const
354     {
355         return taskExecutor_ ? taskExecutor_->PostDelayedTask(std::move(task), type_, delayTime, caller) : false;
356     }
357 
358     /**
359      * Post a delayed task to the specified thread.
360      * Never allow to post a background delayed task.
361      *
362      * @param task Task which need execution.
363      * @param delayTime Wait a period of time in milliseconds before execution.
364      * @return Returns 'true' if task has been posted successfully.
365      */
366     bool PostDelayedTask(const Task& task, uint32_t delayTime, const Caller& caller = {}) const
367     {
368         return taskExecutor_ ? taskExecutor_->PostDelayedTask(task, type_, delayTime, caller) : false;
369     }
370 
371     /**
372      * Post a task to the specified thread and wait until finished executing.
373      * Never allow to post a background synchronous task.
374      *
375      * @param task Task which need execution.
376      * @return Returns 'true' whether task has been executed.
377      */
378     bool PostSyncTask(Task&& task, const Caller& caller = {}) const
379     {
380         return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_, caller) : false;
381     }
382 
383     /**
384      * Post a task to the specified thread and wait until finished executing.
385      * Never allow to post a background synchronous task.
386      *
387      * @param task Task which need execution.
388      * @return Returns 'true' whether task has been executed.
389      */
390     bool PostSyncTask(const Task& task, const Caller& caller = {}) const
391     {
392         return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_, caller) : false;
393     }
394 
395     /**
396      * Post a cancelable task to the specified thread and wait until finished executing.
397      * Never allow to post a background synchronous task.
398      *
399      * @param task Task which need execution.
400      * @return Returns 'true' whether task has been executed.
401      */
402     bool PostSyncTask(CancelableTask&& task, const Caller& caller = {}) const
403     {
404         return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_, caller) : false;
405     }
406 
407     /**
408      * Post a cancelable task to the specified thread and wait until finished executing.
409      * Never allow to post a background synchronous task.
410      *
411      * @param task Task which need execution.
412      * @return Returns 'true' whether task has been executed.
413      */
414     bool PostSyncTask(const CancelableTask& task, const Caller& caller = {}) const
415     {
416         return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_, caller) : false;
417     }
418 
GetTaskExecutor()419     RefPtr<TaskExecutor> GetTaskExecutor() const
420     {
421         return taskExecutor_;
422     }
423 
IsRunOnCurrentThread()424     bool IsRunOnCurrentThread() const
425     {
426         return taskExecutor_ ? taskExecutor_->WillRunOnCurrentThread(type_) : false;
427     }
428 
429 private:
430     RefPtr<TaskExecutor> taskExecutor_;
431     TaskExecutor::TaskType type_;
432 };
433 
434 } // namespace OHOS::Ace
435 
436 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H
437