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();
137 public: // Worker thread called method
139 * Pop the next task out from the queue.
141 * @return The next task to be processed.
143 AsyncTaskPtr PopNextTaskToProcess();
146 * Pop the next task out from the running queue and add this task to the completed queue.
148 * @param[in] task The task added to the queue.
150 void CompleteTask(AsyncTaskPtr task);
152 protected: // Implementation of Processor
154 * @copydoc Dali::Integration::Processor::Process()
156 void Process(bool postProcessor) override;
160 * @brief Helper class to keep the relation between AsyncTaskThread and corresponding container
166 * @brief Create an TaskHelper.
168 * @param[in] asyncTaskManager Reference to the AsyncTaskManager
170 TaskHelper(AsyncTaskManager& asyncTaskManager);
173 * @brief Request the thread to process the task.
174 * @return True if the request succeeds, otherwise false.
179 TaskHelper(const TaskHelper&) = delete;
180 TaskHelper& operator=(const TaskHelper&) = delete;
182 TaskHelper(TaskHelper&& rhs);
183 TaskHelper& operator=(TaskHelper&& rhs) = delete;
187 * @brief Main constructor that used by all other constructors
189 TaskHelper(std::unique_ptr<AsyncTaskThread> processor, AsyncTaskManager& asyncTaskManager);
192 std::unique_ptr<AsyncTaskThread> mProcessor;
193 AsyncTaskManager& mAsyncTaskManager;
197 * @brief State of running task
199 enum RunningTaskState
201 RUNNING = 0, ///< Running task
202 CANCELED = 1, ///< Canceled by user
207 AsyncTaskManager(const AsyncTaskManager& manager);
210 AsyncTaskManager& operator=(const AsyncTaskManager& manager);
213 // Keep Task as list since we take tasks by FIFO as default.
214 using AsyncTaskContainer = std::list<AsyncTaskPtr>;
216 using AsyncTaskPair = std::pair<AsyncTaskPtr, RunningTaskState>;
217 using AsyncRunningTaskContainer = std::list<AsyncTaskPair>;
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.
223 RoundRobinContainerView<TaskHelper> mTasks;
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.
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.
237 std::unique_ptr<CacheImpl> mCacheImpl; ///< Cache interface for AsyncTaskManager.
239 std::unique_ptr<EventThreadCallback> mTrigger;
241 bool mProcessorRegistered : 1;
244 } // namespace Adaptor
246 } // namespace Internal
248 inline Internal::Adaptor::AsyncTaskManager& GetImplementation(Dali::AsyncTaskManager& obj)
250 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
252 Dali::BaseObject& handle = obj.GetBaseObject();
254 return static_cast<Internal::Adaptor::AsyncTaskManager&>(handle);
257 inline const Internal::Adaptor::AsyncTaskManager& GetImplementation(const Dali::AsyncTaskManager& obj)
259 DALI_ASSERT_ALWAYS(obj && "AsyncTaskManager is empty");
261 const Dali::BaseObject& handle = obj.GetBaseObject();
263 return static_cast<const Internal::Adaptor::AsyncTaskManager&>(handle);