8a67d53b9db28a50448c052e96c3c7a9a5b4310b
[platform/core/uifw/dali-adaptor.git] / dali / internal / system / common / async-task-manager-impl.h
1 #ifndef DALI_INTERNAL_ASYNC_TASK_MANAGER_H
2 #define DALI_INTERNAL_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/devel-api/adaptor-framework/event-thread-callback.h>
22 #include <dali/devel-api/threading/conditional-wait.h>
23 #include <dali/devel-api/threading/mutex.h>
24 #include <dali/devel-api/threading/thread.h>
25 #include <dali/integration-api/adaptor-framework/log-factory-interface.h>
26 #include <dali/integration-api/processor-interface.h>
27 #include <dali/public-api/common/list-wrapper.h>
28 #include <dali/public-api/object/base-object.h>
29 #include <memory>
30
31 // INTERNAL INCLUDES
32 #include <dali/public-api/adaptor-framework/async-task-manager.h>
33 #include <dali/public-api/adaptor-framework/round-robin-container-view.h>
34
35 namespace Dali
36 {
37 namespace Internal
38 {
39 namespace Adaptor
40 {
41 class AsyncTaskManager;
42
43 /**
44  * The worker thread for async process
45  */
46 class AsyncTaskThread : public Thread
47 {
48 public:
49   /**
50    * Constructor.
51    */
52   AsyncTaskThread(AsyncTaskManager& asyncTaskManager);
53
54   /**
55    * Destructor.
56    */
57   ~AsyncTaskThread() override;
58
59   /**
60    * @brief Request the thread to process the task.
61    * @return True if the request is successed, otherwise false.
62    */
63   bool Request();
64
65 protected:
66   /**
67    * The entry function of the worker thread.
68    */
69   void Run() override;
70
71 private:
72   // Undefined
73   AsyncTaskThread(const AsyncTaskThread& thread) = delete;
74
75   // Undefined
76   AsyncTaskThread& operator=(const AsyncTaskThread& thread) = delete;
77
78 private:
79   ConditionalWait                  mConditionalWait;
80   AsyncTaskManager&                mAsyncTaskManager;
81   const Dali::LogFactoryInterface& mLogFactory; ///< The log factory
82   bool                             mDestroyThread;
83   bool                             mIsThreadStarted;
84   bool                             mIsThreadIdle;
85 };
86
87 /**
88  * The manager for async task
89  */
90 class AsyncTaskManager : public Dali::BaseObject, public Integration::Processor
91 {
92 public:
93   /**
94    * Singleton access
95    *
96    * @return The AsyncTaskManager object
97    */
98   static Dali::AsyncTaskManager Get();
99
100   /**
101    * Constructor.
102    */
103   AsyncTaskManager();
104
105   /**
106    * Destructor.
107    */
108   ~AsyncTaskManager() override;
109
110   /**
111    * @copydoc Dali::AsyncTaskManager::AddTask()
112    */
113   void AddTask(AsyncTaskPtr task);
114
115   /**
116    * @copydoc Dali::AsyncTaskManager::RemoveTask()
117    */
118   void RemoveTask(AsyncTaskPtr task);
119
120   /**
121    * Pop the next task out from the completed queue, called by main thread.
122    *
123    * @return The next task in the completed queue.
124    */
125   AsyncTaskPtr PopNextCompletedTask();
126
127   /**
128    * @brief Unregister a previously registered processor
129    */
130   void UnregisterProcessor();
131
132   /**
133    * Execute the callback registered by tasks in the completed queue
134    */
135   void TasksCompleted();
136
137 public: // Worker thread called method
138   /**
139    * Pop the next task out from the queue.
140    *
141    * @return The next task to be processed.
142    */
143   AsyncTaskPtr PopNextTaskToProcess();
144
145   /**
146    * Pop the next task out from the running queue and add this task to the completed queue.
147    *
148    * @param[in] task The task added to the queue.
149    */
150   void CompleteTask(AsyncTaskPtr task);
151
152 protected: // Implementation of Processor
153   /**
154    * @copydoc Dali::Integration::Processor::Process()
155    */
156   void Process(bool postProcessor) override;
157
158 private:
159   /**
160    * @brief Helper class to keep the relation between AsyncTaskThread and corresponding container
161    */
162   class TaskHelper
163   {
164   public:
165     /**
166      * @brief Create an TaskHelper.
167      *
168      * @param[in] asyncTaskManager Reference to the AsyncTaskManager
169      */
170     TaskHelper(AsyncTaskManager& asyncTaskManager);
171
172     /**
173      * @brief Request the thread to process the task.
174      * @return True if the request succeeds, otherwise false.
175      */
176     bool Request();
177
178   public:
179     TaskHelper(const TaskHelper&) = delete;
180     TaskHelper& operator=(const TaskHelper&) = delete;
181
182     TaskHelper(TaskHelper&& rhs);
183     TaskHelper& operator=(TaskHelper&& rhs) = delete;
184
185   private:
186     /**
187      * @brief Main constructor that used by all other constructors
188      */
189     TaskHelper(std::unique_ptr<AsyncTaskThread> processor, AsyncTaskManager& asyncTaskManager);
190
191   private:
192     std::unique_ptr<AsyncTaskThread> mProcessor;
193     AsyncTaskManager&                mAsyncTaskManager;
194   };
195
196   /**
197    * @brief State of running task
198    */
199   enum RunningTaskState
200   {
201     RUNNING  = 0, ///< Running task
202     CANCELED = 1, ///< Canceled by user
203   };
204
205 private:
206   // Undefined
207   AsyncTaskManager(const AsyncTaskManager& manager);
208
209   // Undefined
210   AsyncTaskManager& operator=(const AsyncTaskManager& manager);
211
212 private:
213   // Keep Task as list since we take tasks by FIFO as default.
214   using AsyncTaskContainer = std::list<AsyncTaskPtr>;
215
216   using AsyncTaskPair             = std::pair<AsyncTaskPtr, RunningTaskState>;
217   using AsyncRunningTaskContainer = std::list<AsyncTaskPair>;
218
219   AsyncTaskContainer        mWaitingTasks;   ///< The queue of the tasks waiting to async process. Must be locked under mWaitingTasksMutex.
220   AsyncRunningTaskContainer mRunningTasks;   ///< The queue of the running tasks. Must be locked under mRunningTasksMutex.
221   AsyncTaskContainer        mCompletedTasks; ///< The queue of the tasks with the async process. Must be locked under mCompletedTasksMutex.
222
223   RoundRobinContainerView<TaskHelper> mTasks;
224
225   uint32_t mAvaliableLowPriorityTaskCounts; ///< The number of tasks that can be processed for priority type LOW.
226                                             ///< Be used to select next wating task determining algorithm.
227                                             ///< Note : For thread safety, Please set/get this value under mRunningTasksMutex scope.
228   uint32_t mWaitingHighProirityTaskCounts;  ///< The number of tasks that waiting now for priority type HIGH.
229                                             ///< Be used to select next wating task determining algorithm.
230                                             ///< Note : For thread safety, Please set/get this value under mWaitingTasksMutex scope.
231
232   Dali::Mutex mWaitingTasksMutex;   ///< Mutex for mWaitingTasks. We can lock mRunningTasksMutex and mCompletedTasksMutex under this scope.
233   Dali::Mutex mRunningTasksMutex;   ///< Mutex for mRunningTasks. We can lock mCompletedTasksMutex under this scope.
234   Dali::Mutex mCompletedTasksMutex; ///< Mutex for mCompletedTasks. We cannot lock any mutex under this scope.
235
236   struct CacheImpl;
237   std::unique_ptr<CacheImpl> mCacheImpl; ///< Cache interface for AsyncTaskManager.
238
239   std::unique_ptr<EventThreadCallback> mTrigger;
240
241   bool mProcessorRegistered : 1;
242 };
243
244 } // namespace Adaptor
245
246 } // namespace Internal
247
248 inline Internal::Adaptor::AsyncTaskManager& GetImplementation(Dali::AsyncTaskManager& obj)
249 {
250   DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
251
252   Dali::BaseObject& handle = obj.GetBaseObject();
253
254   return static_cast<Internal::Adaptor::AsyncTaskManager&>(handle);
255 }
256
257 inline const Internal::Adaptor::AsyncTaskManager& GetImplementation(const Dali::AsyncTaskManager& obj)
258 {
259   DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
260
261   const Dali::BaseObject& handle = obj.GetBaseObject();
262
263   return static_cast<const Internal::Adaptor::AsyncTaskManager&>(handle);
264 }
265
266 } // namespace Dali
267
268 #endif