[dali_2.3.25] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / public-api / adaptor-framework / async-task-manager.h
1 #ifndef DALI_ASYNC_TASK_MANAGER_H
2 #define DALI_ASYNC_TASK_MANAGER_H
3
4 /*
5  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/common/intrusive-ptr.h>
22 #include <dali/public-api/object/base-handle.h>
23 #include <dali/public-api/signals/callback.h>
24 #include <memory>
25 #include <string_view>
26
27 // INTERNAL INCLUDES
28 #include <dali/public-api/dali-adaptor-common.h>
29
30 namespace Dali
31 {
32 namespace Internal DALI_INTERNAL
33 {
34 namespace Adaptor
35 {
36 class AsyncTaskManager;
37 }
38 } // namespace DALI_INTERNAL
39
40 class AsyncTask;
41 using AsyncTaskPtr = IntrusivePtr<AsyncTask>;
42
43 /**
44  * The async tasks to be processed in the worker thread.
45  * @SINCE_2_2.3
46  */
47 class DALI_ADAPTOR_API AsyncTask : public RefObject
48 {
49 public:
50   // The Type of invocation thread
51   enum class ThreadType
52   {
53     MAIN_THREAD,
54     WORKER_THREAD
55   };
56
57   /**
58    * @brief The priority of this task what user think.
59    * To avoid long term tasks (like remote image download) block whole threads,
60    * Let user set the priority type of this task.
61    *
62    * Low priority task means it doesn't need to process by FIFO logic.
63    * So we make that Low priority don't take whole threads.
64    *
65    * Task selection algorithm defined internally.
66    *
67    * @note Task cannot change the priority type after create.
68    *
69    * @SINCE_2_2.17
70    */
71   enum class PriorityType
72   {
73     HIGH = 0, ///< Highest priority to process task. @SINCE_2_2.17
74     LOW  = 1, ///< Lowest priority to process task. @SINCE_2_2.17
75
76     PRIORITY_COUNT, ///< The number of priority type. @SINCE_2_2.17
77
78     DEFAULT = HIGH, ///< Default priority value if nothing defined. @SINCE_2_2.17
79   };
80
81   /**
82    * Constructor
83    * @SINCE_2_2.3
84    * @param[in] callback The callback to invoke on task completion, either on the main thread on the worker thread. The ownership of callback is taken by this class.
85    * @param[in] priority The proirity type of this task.
86    * @param[in] threadType The thread type of invocation callback.
87    */
88   AsyncTask(CallbackBase* callback, PriorityType priority = PriorityType::DEFAULT, ThreadType threadType = AsyncTask::ThreadType::MAIN_THREAD);
89
90   /**
91    * Get the complated callback
92    * @SINCE_2_2.3
93    */
94   CallbackBase* GetCompletedCallback();
95
96   /**
97    * Get the thread of the invocation callback
98    * @SINCE_2_2.9
99    * @return the type of invocation callback.
100    */
101   ThreadType GetCallbackInvocationThread() const;
102
103   /**
104    * Get the priority of this task
105    * @SINCE_2_2.17
106    * @return the type of priority.
107    */
108   PriorityType GetPriorityType() const;
109
110   /**
111    * Destructor.
112    * @SINCE_2_2.3
113    */
114   virtual ~AsyncTask() = default;
115
116   /**
117    * Process the task
118    * @SINCE_2_2.3
119    */
120   virtual void Process() = 0;
121
122   /**
123    * Whether the task is ready to process.
124    * @SINCE_2_2.3
125    * @return True if the task is ready to process.
126    */
127   virtual bool IsReady() = 0;
128
129   /**
130    * Get the name of this task if we setup.
131    * @SINCE_2_3.4
132    * @return The name of this task.
133    */
134   virtual std::string_view GetTaskName() const
135   {
136     Dali::DaliPrintBackTrace();
137     return "";
138   }
139
140 private:
141   std::unique_ptr<CallbackBase> mCompletedCallback;
142   const PriorityType            mPriorityType;
143   ThreadType                    mThreadType;
144
145   // Undefined
146   AsyncTask(const AsyncTask& task) = delete;
147
148   // Undefined
149   AsyncTask& operator=(const AsyncTask& task) = delete;
150 };
151
152 /**
153  * The manager for async task
154  * @SINCE_2_2.3
155  */
156 class DALI_ADAPTOR_API AsyncTaskManager : public BaseHandle
157 {
158 public:
159   /**
160    * Constructor.
161    * @SINCE_2_2.3
162    */
163   AsyncTaskManager();
164
165   /**
166    * Destructor.
167    * @SINCE_2_2.3
168    */
169   ~AsyncTaskManager();
170
171   /**
172    * @brief Gets the singleton of AsyncTaskManager object.
173    *
174    * @SINCE_2_2.3
175    * @return A handle to the AsyncTaskManager
176    */
177   static AsyncTaskManager Get();
178
179   /**
180    * @brief Add the async task into the waiting queue, called by main thread.
181    *
182    * @SINCE_2_2.3
183    * @param[in] task The task added to the queue.
184    */
185   void AddTask(AsyncTaskPtr task);
186
187   /**
188    * @brief Remove the task from the waiting queue, called by main thread.
189    *
190    * @SINCE_2_2.3
191    * @param[in] task The task pointer.
192    */
193   void RemoveTask(AsyncTaskPtr task);
194
195 public:
196   using TasksCompletedId = uint32_t;
197
198   enum CompletedCallbackTraceMask
199   {
200     THREAD_MASK_MAIN   = 1u << 0, ///< Trace only main thread tasks.
201     THREAD_MASK_WORKER = 1u << 1, ///< Trace only worker thread tasks.
202
203     PRIORITY_MASK_HIGH = 1u << 2, ///< Trace only high priority tasks.
204     PRIORITY_MASK_LOW  = 1u << 3, ///< Trace only low priority tasks.
205
206     THREAD_MASK_ALL   = THREAD_MASK_MAIN | THREAD_MASK_WORKER,
207     PRIORITY_MASK_ALL = PRIORITY_MASK_HIGH | PRIORITY_MASK_LOW,
208
209     // Useful preset of task mask.
210
211     MAIN_THREAD_TASKS   = THREAD_MASK_MAIN | PRIORITY_MASK_ALL,
212     WORKER_THREAD_TASKS = THREAD_MASK_WORKER | PRIORITY_MASK_ALL,
213     HIGH_PRIORITY_TASKS = THREAD_MASK_ALL | PRIORITY_MASK_HIGH,
214     LOW_PRIORITY_TASKS  = THREAD_MASK_ALL | PRIORITY_MASK_LOW,
215
216     MAIN_THREAD_HIGH_PRIORITY_TASKS = THREAD_MASK_MAIN | PRIORITY_MASK_HIGH,
217     MAIN_THREAD_LOW_PRIORITY_TASKS  = THREAD_MASK_MAIN | PRIORITY_MASK_LOW,
218
219     ALL_TASKS = THREAD_MASK_ALL | PRIORITY_MASK_ALL,
220
221     DEFAULT = ALL_TASKS,
222   };
223
224   /**
225    * @brief Set the async tasks completed callback.
226    * Inputed callback will be emitted after all tasks what user added are completed.
227    *
228    * Usage example:
229    *
230    *   void OnTasksCompleted(TasksCompletedId id);
231    *   auto id0 = AsyncTaskManager::Get().SetCompletedCallback(MakeCallback(OnTasksCompleted), CompletedCallbackTraceMask::MASK_ALL);
232    *   // OnTasksCompleted(id0); called at next Idler.
233    *
234    *   AsyncTaskManager::Get().AddTask(task1);
235    *   auto id1 = AsyncTaskManager::Get().SetCompletedCallback(MakeCallback(OnTasksCompleted), CompletedCallbackTraceMask::MASK_ALL);
236    *   // OnTasksCompleted(id1); called after task1 completed.
237    *
238    *   AsyncTaskManager::Get().AddTask(task2WhichIsLowPriority);
239    *   AsyncTaskManager::Get().AddTask(task3WhichIsWorkerThread);
240    *   AsyncTaskManager::Get().AddTask(task4);
241    *   auto id2 = AsyncTaskManager::Get().SetCompletedCallback(MakeCallback(OnTasksCompleted), static_cast<CompletedCallbackTraceMask>(CompletedCallbackTraceMask::THREAD_MASK_MAIN | CompletedCallbackTraceMask::PRIORITY_MASK_HIGH));
242    *   // OnTasksCompleted(id2); called after task1 and task4 completed.
243    *
244    *   AsyncTaskManager::Get().RemoveCompletedCallback(id1);
245    *   // OnTasksCompleted(id1); will not be called.
246    *
247    * @note The ownership of callback will be hold AsyncTaskManager itself.
248    * @note The callback will be emmited at Process() timming.
249    *
250    * @SINCE_2_2.52
251    * @param[in] callback The callback base when all AsyncTasks completed.
252    *                     This callback will be void return, and single input argument ; TasksCompletedId.
253    * @param[in] mask Mask info s.t. what kind of async task we want to detact.
254    *                 For example, if we set this value as MASK_ALL & ~PRIORITY_MASK_LOW, we will ignore low priority tasks.
255    *                 Default is MASK_ALL.
256    * @return The unique id for callback. It can be used when we want to remove callback.
257    */
258   TasksCompletedId SetCompletedCallback(CallbackBase* callback, CompletedCallbackTraceMask mask = CompletedCallbackTraceMask::DEFAULT);
259
260   /**
261    * @brief Remove the async tasks completed callback.
262    * @note It will not execute setted callback.
263    *
264    * @SINCE_2_2.52
265    * @param[in] tasksCompletedId The id for callback that want to remove.
266    * @return True if we success to removed. False if it already removed, or callback already emitted.
267    */
268   bool RemoveCompletedCallback(TasksCompletedId tasksCompletedId);
269
270 public:
271   /// @cond internal
272   /**
273    * @brief Allows the creation of a AsyncTaskManager handle from an internal pointer.
274    *
275    * @note Not intended for application developers
276    * @SINCE_2_2.3
277    * @param[in] impl A pointer to the object
278    */
279   explicit DALI_INTERNAL AsyncTaskManager(Internal::Adaptor::AsyncTaskManager* impl);
280   /// @endcond
281 };
282
283 } // namespace Dali
284
285 #endif