• 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;
Destory()220     virtual void Destory() {}
221 
GetTid(TaskType type)222     virtual int32_t GetTid(TaskType type)
223     {
224         return 0;
225     }
226 
GetTotalTaskNum(TaskType type)227     virtual uint32_t GetTotalTaskNum(TaskType type)
228     {
229         return 0;
230     }
231 
232 protected:
233     TaskExecutor() = default;
234 
235     virtual bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const = 0;
236     virtual Task WrapTaskWithTraceId(Task&& task, int32_t id) const = 0;
237 
238 #ifdef ACE_DEBUG
OnPreSyncTask(TaskType type)239     virtual bool OnPreSyncTask(TaskType type) const
240     {
241         return true;
242     }
OnPostSyncTask()243     virtual void OnPostSyncTask() const {}
244 #endif
245 
246 private:
247     bool PostTaskAndWait(CancelableTask&& task, TaskType type, std::chrono::milliseconds timeoutMs = 0ms) const
248     {
249 #ifdef ACE_DEBUG
250         bool result = false;
251         if (OnPreSyncTask(type)) {
252             result = OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs);
253             OnPostSyncTask();
254         }
255         return result;
256 #else
257         return OnPostTask(Task(task), type, 0) && task.WaitUntilComplete(timeoutMs);
258 #endif
259     }
260 };
261 
262 class SingleTaskExecutor final {
263 public:
264     using Task = TaskExecutor::Task;
265     using CancelableTask = TaskExecutor::CancelableTask;
266     using TaskType = TaskExecutor::TaskType;
267 
SingleTaskExecutor(RefPtr<TaskExecutor> && taskExecutor,TaskType type)268     SingleTaskExecutor(RefPtr<TaskExecutor>&& taskExecutor, TaskType type)
269         : taskExecutor_(std::move(taskExecutor)), type_(type)
270     {}
SingleTaskExecutor(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)271     SingleTaskExecutor(const RefPtr<TaskExecutor>& taskExecutor, TaskType type)
272         : taskExecutor_(taskExecutor), type_(type)
273     {}
274     ~SingleTaskExecutor() = default;
275 
Make(RefPtr<TaskExecutor> && taskExecutor,TaskType type)276     static SingleTaskExecutor Make(RefPtr<TaskExecutor>&& taskExecutor, TaskType type)
277     {
278         return SingleTaskExecutor(std::move(taskExecutor), type);
279     }
280 
Make(const RefPtr<TaskExecutor> & taskExecutor,TaskType type)281     static SingleTaskExecutor Make(const RefPtr<TaskExecutor>& taskExecutor, TaskType type)
282     {
283         return SingleTaskExecutor(taskExecutor, type);
284     }
285 
286     /**
287      * Post a task to the specified thread.
288      *
289      * @param task Task which need execution.
290      * @return Returns 'true' whether task has been post successfully.
291      */
PostTask(Task && task)292     bool PostTask(Task&& task) const
293     {
294         return taskExecutor_ ? taskExecutor_->PostTask(std::move(task), type_) : false;
295     }
296 
297     /**
298      * Post a task to the specified thread.
299      *
300      * @param task Task which need execution.
301      * @return Returns 'true' whether task has been post successfully.
302      */
PostTask(const Task & task)303     bool PostTask(const Task& task) const
304     {
305         return taskExecutor_ ? taskExecutor_->PostTask(task, type_) : false;
306     }
307 
308     /**
309      * Post a delayed task to the specified thread.
310      * Never allow to post a background delayed task.
311      *
312      * @param task Task which need execution.
313      * @param delayTime Wait a period of time in milliseconds before execution.
314      * @return Returns 'true' if task has been posted successfully.
315      */
PostDelayedTask(Task && task,uint32_t delayTime)316     bool PostDelayedTask(Task&& task, uint32_t delayTime) const
317     {
318         return taskExecutor_ ? taskExecutor_->PostDelayedTask(std::move(task), type_, delayTime) : false;
319     }
320 
321     /**
322      * Post a delayed task to the specified thread.
323      * Never allow to post a background delayed task.
324      *
325      * @param task Task which need execution.
326      * @param delayTime Wait a period of time in milliseconds before execution.
327      * @return Returns 'true' if task has been posted successfully.
328      */
PostDelayedTask(const Task & task,uint32_t delayTime)329     bool PostDelayedTask(const Task& task, uint32_t delayTime) const
330     {
331         return taskExecutor_ ? taskExecutor_->PostDelayedTask(task, type_, delayTime) : false;
332     }
333 
334     /**
335      * Post a task to the specified thread and wait until finished executing.
336      * Never allow to post a background synchronous task.
337      *
338      * @param task Task which need execution.
339      * @return Returns 'true' whether task has been executed.
340      */
PostSyncTask(Task && task)341     bool PostSyncTask(Task&& task) const
342     {
343         return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false;
344     }
345 
346     /**
347      * Post a task to the specified thread and wait until finished executing.
348      * Never allow to post a background synchronous task.
349      *
350      * @param task Task which need execution.
351      * @return Returns 'true' whether task has been executed.
352      */
PostSyncTask(const Task & task)353     bool PostSyncTask(const Task& task) const
354     {
355         return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false;
356     }
357 
358     /**
359      * Post a cancelable task to the specified thread and wait until finished executing.
360      * Never allow to post a background synchronous task.
361      *
362      * @param task Task which need execution.
363      * @return Returns 'true' whether task has been executed.
364      */
PostSyncTask(CancelableTask && task)365     bool PostSyncTask(CancelableTask&& task) const
366     {
367         return taskExecutor_ ? taskExecutor_->PostSyncTask(std::move(task), type_) : false;
368     }
369 
370     /**
371      * Post a cancelable task to the specified thread and wait until finished executing.
372      * Never allow to post a background synchronous task.
373      *
374      * @param task Task which need execution.
375      * @return Returns 'true' whether task has been executed.
376      */
PostSyncTask(const CancelableTask & task)377     bool PostSyncTask(const CancelableTask& task) const
378     {
379         return taskExecutor_ ? taskExecutor_->PostSyncTask(task, type_) : false;
380     }
381 
GetTaskExecutor()382     RefPtr<TaskExecutor> GetTaskExecutor() const
383     {
384         return taskExecutor_;
385     }
386 
IsRunOnCurrentThread()387     bool IsRunOnCurrentThread() const
388     {
389         return taskExecutor_ ? taskExecutor_->WillRunOnCurrentThread(type_) : false;
390     }
391 
392 private:
393     RefPtr<TaskExecutor> taskExecutor_;
394     TaskExecutor::TaskType type_;
395 };
396 
397 } // namespace OHOS::Ace
398 
399 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_TASK_EXECUTOR_H
400