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/processor-interface.h>
27 #include <dali/public-api/common/list-wrapper.h>
28 #include <dali/public-api/object/base-object.h>
32 #include <dali/public-api/adaptor-framework/async-task-manager.h>
33 #include <dali/public-api/adaptor-framework/round-robin-container-view.h>
41 class AsyncTaskManager;
44 * The worker thread for async process
46 class AsyncTaskThread : public Thread
52 AsyncTaskThread(AsyncTaskManager& asyncTaskManager);
57 ~AsyncTaskThread() override;
60 * @brief Request the thread to process the task.
61 * @return True if the request is successed, otherwise false.
67 * The entry function of the worker thread.
73 AsyncTaskThread(const AsyncTaskThread& thread) = delete;
76 AsyncTaskThread& operator=(const AsyncTaskThread& thread) = delete;
79 ConditionalWait mConditionalWait;
80 AsyncTaskManager& mAsyncTaskManager;
81 const Dali::LogFactoryInterface& mLogFactory; ///< The log factory
83 bool mIsThreadStarted;
88 * The manager for async task
90 class AsyncTaskManager : public Dali::BaseObject, public Integration::Processor
96 * @return The AsyncTaskManager object
98 static Dali::AsyncTaskManager Get();
108 ~AsyncTaskManager() override;
111 * @copydoc Dali::AsyncTaskManager::AddTask()
113 void AddTask(AsyncTaskPtr task);
116 * @copydoc Dali::AsyncTaskManager::RemoveTask()
118 void RemoveTask(AsyncTaskPtr task);
121 * Pop the next task out from the completed queue, called by main thread.
123 * @return The next task in the completed queue.
125 AsyncTaskPtr PopNextCompletedTask();
128 * @brief Unregister a previously registered processor
130 void UnregisterProcessor();
133 * Execute the callback registered by tasks in the completed queue
135 void TasksCompleted();
138 * @copydoc Dali::Integration::Processor::Process()
140 void Process(bool postProcessor) override;
142 public: // Worker thread called method
144 * Pop the next task out from the queue.
146 * @return The next task to be processed.
148 AsyncTaskPtr PopNextTaskToProcess();
151 * Pop the next task out from the running queue and add this task to the completed queue.
153 * @param[in] task The task added to the queue.
155 void CompleteTask(AsyncTaskPtr task);
159 * @brief Helper class to keep the relation between AsyncTaskThread and corresponding container
165 * @brief Create an TaskHelper.
167 * @param[in] asyncTaskManager Reference to the AsyncTaskManager
169 TaskHelper(AsyncTaskManager& asyncTaskManager);
172 * @brief Request the thread to process the task.
173 * @return True if the request succeeds, otherwise false.
178 TaskHelper(const TaskHelper&) = delete;
179 TaskHelper& operator=(const TaskHelper&) = delete;
181 TaskHelper(TaskHelper&& rhs);
182 TaskHelper& operator=(TaskHelper&& rhs) = delete;
186 * @brief Main constructor that used by all other constructors
188 TaskHelper(std::unique_ptr<AsyncTaskThread> processor, AsyncTaskManager& asyncTaskManager);
191 std::unique_ptr<AsyncTaskThread> mProcessor;
192 AsyncTaskManager& mAsyncTaskManager;
197 AsyncTaskManager(const AsyncTaskManager& manager);
200 AsyncTaskManager& operator=(const AsyncTaskManager& manager);
203 using AsyncTaskContainer = std::list<AsyncTaskPtr>;
205 using AsyncTaskPair = std::pair<AsyncTaskPtr, bool>;
206 using AsyncRunningTaskContainer = std::list<AsyncTaskPair>;
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.
212 RoundRobinContainerView<TaskHelper> mTasks;
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.
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.
226 std::unique_ptr<CacheImpl> mCacheImpl; ///< Cache interface for AsyncTaskManager.
228 std::unique_ptr<EventThreadCallback> mTrigger;
229 bool mProcessorRegistered;
232 } // namespace Adaptor
234 } // namespace Internal
236 inline Internal::Adaptor::AsyncTaskManager& GetImplementation(Dali::AsyncTaskManager& obj)
238 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
240 Dali::BaseObject& handle = obj.GetBaseObject();
242 return static_cast<Internal::Adaptor::AsyncTaskManager&>(handle);
245 inline const Internal::Adaptor::AsyncTaskManager& GetImplementation(const Dali::AsyncTaskManager& obj)
247 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
249 const Dali::BaseObject& handle = obj.GetBaseObject();
251 return static_cast<const Internal::Adaptor::AsyncTaskManager&>(handle);