1 #ifndef DALI_INTERNAL_ASYNC_TASK_MANAGER_H
2 #define DALI_INTERNAL_ASYNC_TASK_MANAGER_H
5 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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/adaptor-framework/trace-factory-interface.h>
27 #include <dali/integration-api/processor-interface.h>
28 #include <dali/public-api/common/list-wrapper.h>
29 #include <dali/public-api/object/base-object.h>
33 #include <dali/public-api/adaptor-framework/async-task-manager.h>
34 #include <dali/public-api/adaptor-framework/round-robin-container-view.h>
42 class AsyncTaskManager;
45 * The worker thread for async process
47 class AsyncTaskThread : public Thread
53 AsyncTaskThread(AsyncTaskManager& asyncTaskManager);
58 ~AsyncTaskThread() override;
61 * @brief Request the thread to process the task.
62 * @return True if the request is successed, otherwise false.
68 * The entry function of the worker thread.
74 AsyncTaskThread(const AsyncTaskThread& thread) = delete;
77 AsyncTaskThread& operator=(const AsyncTaskThread& thread) = delete;
80 ConditionalWait mConditionalWait;
81 AsyncTaskManager& mAsyncTaskManager;
82 const Dali::LogFactoryInterface& mLogFactory; ///< The log factory
83 const Dali::TraceFactoryInterface& mTraceFactory; ///< The trace factory
85 bool mIsThreadStarted;
90 * The manager for async task
92 class AsyncTaskManager : public Dali::BaseObject, public Integration::Processor
98 * @return The AsyncTaskManager object
100 static Dali::AsyncTaskManager Get();
110 ~AsyncTaskManager() override;
113 * @copydoc Dali::AsyncTaskManager::AddTask()
115 void AddTask(AsyncTaskPtr task);
118 * @copydoc Dali::AsyncTaskManager::RemoveTask()
120 void RemoveTask(AsyncTaskPtr task);
123 * Pop the next task out from the completed queue, called by main thread.
125 * @return The next task in the completed queue.
127 AsyncTaskPtr PopNextCompletedTask();
130 * @brief Unregister a previously registered processor
132 void UnregisterProcessor();
135 * Execute the callback registered by tasks in the completed queue
137 void TasksCompleted();
139 public: // Worker thread called method
141 * Pop the next task out from the queue.
143 * @return The next task to be processed.
145 AsyncTaskPtr PopNextTaskToProcess();
148 * Pop the next task out from the running queue and add this task to the completed queue.
149 * @note After this function, task is invalidate.
151 * @param[in] task The task added to the queue.
153 void CompleteTask(AsyncTaskPtr&& task);
155 protected: // Implementation of Processor
157 * @copydoc Dali::Integration::Processor::Process()
159 void Process(bool postProcessor) override;
163 * @brief Helper class to keep the relation between AsyncTaskThread and corresponding container
169 * @brief Create an TaskHelper.
171 * @param[in] asyncTaskManager Reference to the AsyncTaskManager
173 TaskHelper(AsyncTaskManager& asyncTaskManager);
176 * @brief Request the thread to process the task.
177 * @return True if the request succeeds, otherwise false.
182 TaskHelper(const TaskHelper&) = delete;
183 TaskHelper& operator=(const TaskHelper&) = delete;
185 TaskHelper(TaskHelper&& rhs);
186 TaskHelper& operator=(TaskHelper&& rhs) = delete;
190 * @brief Main constructor that used by all other constructors
192 TaskHelper(std::unique_ptr<AsyncTaskThread> processor, AsyncTaskManager& asyncTaskManager);
195 std::unique_ptr<AsyncTaskThread> mProcessor;
196 AsyncTaskManager& mAsyncTaskManager;
200 * @brief State of running task
202 enum class RunningTaskState
204 RUNNING = 0, ///< Running task
205 CANCELED = 1, ///< Canceled by user
209 * @brief State of complete task
211 enum class CompletedTaskState
213 REQUIRE_CALLBACK = 0, ///< Need to execute callback when completed task process.
214 SKIP_CALLBACK = 1, ///< Do not execute callback
219 AsyncTaskManager(const AsyncTaskManager& manager);
222 AsyncTaskManager& operator=(const AsyncTaskManager& manager);
225 // Keep Task as list since we take tasks by FIFO as default.
226 using AsyncTaskContainer = std::list<AsyncTaskPtr>;
228 using AsyncRunningTaskPair = std::pair<AsyncTaskPtr, RunningTaskState>;
229 using AsyncRunningTaskContainer = std::list<AsyncRunningTaskPair>;
231 using AsyncCompletedTaskPair = std::pair<AsyncTaskPtr, CompletedTaskState>;
232 using AsyncCompletedTaskContainer = std::list<AsyncCompletedTaskPair>;
234 AsyncTaskContainer mWaitingTasks; ///< The queue of the tasks waiting to async process. Must be locked under mWaitingTasksMutex.
235 AsyncRunningTaskContainer mRunningTasks; ///< The queue of the running tasks. Must be locked under mRunningTasksMutex.
236 AsyncCompletedTaskContainer mCompletedTasks; ///< The queue of the tasks with the async process. Must be locked under mCompletedTasksMutex.
238 RoundRobinContainerView<TaskHelper> mTasks;
240 uint32_t mAvaliableLowPriorityTaskCounts; ///< The number of tasks that can be processed for priority type LOW.
241 ///< Be used to select next wating task determining algorithm.
242 ///< Note : For thread safety, Please set/get this value under mRunningTasksMutex scope.
243 uint32_t mWaitingHighProirityTaskCounts; ///< The number of tasks that waiting now for priority type HIGH.
244 ///< Be used to select next wating task determining algorithm.
245 ///< Note : For thread safety, Please set/get this value under mWaitingTasksMutex scope.
247 Dali::Mutex mWaitingTasksMutex; ///< Mutex for mWaitingTasks. We can lock mRunningTasksMutex and mCompletedTasksMutex under this scope.
248 Dali::Mutex mRunningTasksMutex; ///< Mutex for mRunningTasks. We can lock mCompletedTasksMutex under this scope.
249 Dali::Mutex mCompletedTasksMutex; ///< Mutex for mCompletedTasks. We cannot lock any mutex under this scope.
252 std::unique_ptr<CacheImpl> mCacheImpl; ///< Cache interface for AsyncTaskManager.
254 std::unique_ptr<EventThreadCallback> mTrigger;
256 bool mProcessorRegistered : 1;
259 } // namespace Adaptor
261 } // namespace Internal
263 inline Internal::Adaptor::AsyncTaskManager& GetImplementation(Dali::AsyncTaskManager& obj)
265 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
267 Dali::BaseObject& handle = obj.GetBaseObject();
269 return static_cast<Internal::Adaptor::AsyncTaskManager&>(handle);
272 inline const Internal::Adaptor::AsyncTaskManager& GetImplementation(const Dali::AsyncTaskManager& obj)
274 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
276 const Dali::BaseObject& handle = obj.GetBaseObject();
278 return static_cast<const Internal::Adaptor::AsyncTaskManager&>(handle);