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