c33f27551c1725a77cac3b2baa9780ee2330b408
[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   /**
138    * @copydoc Dali::Integration::Processor::Process()
139    */
140   void Process(bool postProcessor) override;
141
142 public: // Worker thread called method
143   /**
144    * Pop the next task out from the queue.
145    *
146    * @return The next task to be processed.
147    */
148   AsyncTaskPtr PopNextTaskToProcess();
149
150   /**
151    * Pop the next task out from the running queue and add this task to the completed queue.
152    *
153    * @param[in] task The task added to the queue.
154    */
155   void CompleteTask(AsyncTaskPtr task);
156
157 private:
158   /**
159    * @brief Helper class to keep the relation between AsyncTaskThread and corresponding container
160    */
161   class TaskHelper
162   {
163   public:
164     /**
165      * @brief Create an TaskHelper.
166      *
167      * @param[in] asyncTaskManager Reference to the AsyncTaskManager
168      */
169     TaskHelper(AsyncTaskManager& asyncTaskManager);
170
171     /**
172      * @brief Request the thread to process the task.
173      * @return True if the request succeeds, otherwise false.
174      */
175     bool Request();
176
177   public:
178     TaskHelper(const TaskHelper&) = delete;
179     TaskHelper& operator=(const TaskHelper&) = delete;
180
181     TaskHelper(TaskHelper&& rhs);
182     TaskHelper& operator=(TaskHelper&& rhs) = delete;
183
184   private:
185     /**
186      * @brief Main constructor that used by all other constructors
187      */
188     TaskHelper(std::unique_ptr<AsyncTaskThread> processor, AsyncTaskManager& asyncTaskManager);
189
190   private:
191     std::unique_ptr<AsyncTaskThread> mProcessor;
192     AsyncTaskManager&                mAsyncTaskManager;
193   };
194
195 private:
196   // Undefined
197   AsyncTaskManager(const AsyncTaskManager& manager);
198
199   // Undefined
200   AsyncTaskManager& operator=(const AsyncTaskManager& manager);
201
202 private:
203   using AsyncTaskContainer = std::list<AsyncTaskPtr>;
204
205   using AsyncTaskPair             = std::pair<AsyncTaskPtr, bool>;
206   using AsyncRunningTaskContainer = std::list<AsyncTaskPair>;
207
208   AsyncTaskContainer        mWaitingTasks;   ///< The queue of the tasks waiting to async process. Must be locked under mWaitingTasksMutex.
209   AsyncRunningTaskContainer mRunningTasks;   ///< The queue of the running tasks. Must be locked under mRunningTasksMutex.
210   AsyncTaskContainer        mCompletedTasks; ///< The queue of the tasks with the async process. Must be locked under mCompletedTasksMutex.
211
212   RoundRobinContainerView<TaskHelper> mTasks;
213
214   uint32_t mAvaliableLowPriorityTaskCounts; ///< The number of tasks that can be processed for priority type LOW.
215                                             ///< Be used to select next wating task determining algorithm.
216                                             ///< Note : For thread safety, Please set/get this value under mRunningTasksMutex scope.
217   uint32_t mWaitingHighProirityTaskCounts;  ///< The number of tasks that waiting now for priority type HIGH.
218                                             ///< Be used to select next wating task determining algorithm.
219                                             ///< Note : For thread safety, Please set/get this value under mWaitingTasksMutex scope.
220
221   Dali::Mutex mWaitingTasksMutex;   ///< Mutex for mWaitingTasks. We can lock mRunningTasksMutex and mCompletedTasksMutex under this scope.
222   Dali::Mutex mRunningTasksMutex;   ///< Mutex for mRunningTasks. We can lock mCompletedTasksMutex under this scope.
223   Dali::Mutex mCompletedTasksMutex; ///< Mutex for mCompletedTasks. We cannot lock any mutex under this scope.
224
225   struct CacheImpl;
226   std::unique_ptr<CacheImpl> mCacheImpl; ///< Cache interface for AsyncTaskManager.
227
228   std::unique_ptr<EventThreadCallback> mTrigger;
229   bool                                 mProcessorRegistered;
230 };
231
232 } // namespace Adaptor
233
234 } // namespace Internal
235
236 inline Internal::Adaptor::AsyncTaskManager& GetImplementation(Dali::AsyncTaskManager& obj)
237 {
238   DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
239
240   Dali::BaseObject& handle = obj.GetBaseObject();
241
242   return static_cast<Internal::Adaptor::AsyncTaskManager&>(handle);
243 }
244
245 inline const Internal::Adaptor::AsyncTaskManager& GetImplementation(const Dali::AsyncTaskManager& obj)
246 {
247   DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
248
249   const Dali::BaseObject& handle = obj.GetBaseObject();
250
251   return static_cast<const Internal::Adaptor::AsyncTaskManager&>(handle);
252 }
253
254 } // namespace Dali
255
256 #endif