1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef API_CORE_THREADING_INTF_THREAD_POOL_H
17 #define API_CORE_THREADING_INTF_THREAD_POOL_H
18
19 #include <cstdint>
20
21 #include <base/containers/refcnt_ptr.h>
22 #include <base/containers/unique_ptr.h>
23 #include <base/containers/vector.h>
24 #include <base/namespace.h>
25 #include <base/util/uid.h>
26 #include <core/namespace.h>
27 #include <core/plugin/intf_interface.h>
28
29 BASE_BEGIN_NAMESPACE()
30 template<class T>
31 class array_view;
32 BASE_END_NAMESPACE()
33
CORE_BEGIN_NAMESPACE()34 CORE_BEGIN_NAMESPACE()
35 /** \addtogroup group_threading
36 * @{
37 */
38 /** Interface for thread safe thread pool.
39 * ITask instances pushed to the queue are executed in different threads and completing can be waited with the returned
40 * IResult.
41 */
42 class IThreadPool : public IInterface {
43 public:
44 static constexpr BASE_NS::Uid UID { "5b0d3810-cbcf-418a-a2e1-5df69fde1c09" };
45
46 using Ptr = BASE_NS::refcnt_ptr<IThreadPool>;
47
48 /** Interface for tasks that can be submitted to execution in the pool. */
49 class ITask {
50 public:
51 virtual void operator()() = 0;
52
53 struct Deleter {
54 constexpr Deleter() noexcept = default;
55 void operator()(ITask* ptr) const
56 {
57 ptr->Destroy();
58 }
59 };
60 using Ptr = BASE_NS::unique_ptr<ITask, Deleter>;
61
62 protected:
63 virtual ~ITask() = default;
64 virtual void Destroy() = 0;
65 };
66
67 /** Interface for result tasks that can be submitted to execution in the pool. */
68 class IResult {
69 public:
70 virtual void Wait() = 0;
71 virtual bool IsDone() const = 0;
72
73 struct Deleter {
74 constexpr Deleter() noexcept = default;
75 void operator()(IResult* ptr) const
76 {
77 ptr->Destroy();
78 }
79 };
80 using Ptr = BASE_NS::unique_ptr<IResult, Deleter>;
81
82 protected:
83 virtual ~IResult() = default;
84 virtual void Destroy() = 0;
85 };
86
87 /** Adds a task to be executed.
88 * @param task Pointer to a task instance.
89 * @return Pointer to a result instance which can be waited
90 */
91 virtual IResult::Ptr Push(ITask::Ptr task) = 0;
92
93 /** Adds a task with a dependency to be executed.
94 * @param task Pointer to a task instance.
95 * @param dependencies Pointers to task instances which must be ready before 'task' can start.
96 * @return Pointer to a result instance which can be waited
97 */
98 virtual IResult::Ptr Push(ITask::Ptr task, BASE_NS::array_view<const ITask* const> dependencies) = 0;
99
100 /** Adds a task to be executed.
101 * @param task Pointer to a task instance.
102 */
103 virtual void PushNoWait(ITask::Ptr task) = 0;
104
105 /** Adds a task with a dependency to be executed.
106 * @param task Pointer to a task instance.
107 * @param dependencies Pointers to task instances which must be ready before 'task' can start.
108 */
109 virtual void PushNoWait(ITask::Ptr task, BASE_NS::array_view<const ITask* const> dependencies) = 0;
110
111 /** Get the number of threads this pool has.
112 * @return Total number of threads in the pool.
113 */
114 virtual uint32_t GetNumberOfThreads() const = 0;
115
116 protected:
117 virtual ~IThreadPool() = default;
118 };
119
120 class ITaskQueue {
121 public:
122 /** Adds a task to be executed later.
123 * @param taskIdentifier Identifier for the task.
124 * @param task Pointer to a task instance.
125 */
126 virtual void Submit(uint64_t taskIdentifier, IThreadPool::ITask::Ptr&& task) = 0;
127
128 /** Adds a task to be executed later with a dependency.
129 * @param afterIdentifier Identifier of the task that must be executed prior this task. If the identifier is
130 * unknown, the task will be added without dependency.
131 * @param taskIdentifier Identifier for the task.
132 * @param task Pointer to a task instance.
133 */
134 virtual void SubmitAfter(uint64_t afterIdentifier, uint64_t taskIdentifier, IThreadPool::ITask::Ptr&& task) = 0;
135
136 /** Adds a task to be executed later with multiple dependencies.
137 * @param afterIdentifiers Identifiers of the tasks that must be executed prior this task. Unknown identifiers will
138 * be skipped.
139 * @param taskIdentifier Identifier for the task.
140 * @param task Pointer to a task instance.
141 */
142 virtual void SubmitAfter(BASE_NS::array_view<const uint64_t> afterIdentifiers, uint64_t taskIdentifier,
143 IThreadPool::ITask::Ptr&& task) = 0;
144
145 /** Remove all tasks from queue. */
146 virtual void Clear() = 0;
147
148 /** Execute tasks in queue. */
149 virtual void Execute() = 0;
150 };
151
152 /** Thread safe task dispatcher, executes one task per execute call and removes it once it is finished.
153 */
154 class IDispatcherTaskQueue : public ITaskQueue {
155 public:
156 /** Reports finished tasks, allows to check which tasks have been completed.
157 * @return Task ids of tasks that have finished.
158 */
159 virtual BASE_NS::vector<uint64_t> CollectFinishedTasks() = 0;
160
161 struct Deleter {
162 constexpr Deleter() noexcept = default;
operatorDeleter163 void operator()(IDispatcherTaskQueue* ptr) const
164 {
165 ptr->Destroy();
166 }
167 };
168 using Ptr = BASE_NS::unique_ptr<IDispatcherTaskQueue, Deleter>;
169
170 protected:
171 IDispatcherTaskQueue() = default;
172 virtual ~IDispatcherTaskQueue() = default;
173 IDispatcherTaskQueue(const IDispatcherTaskQueue& other) = delete;
174 virtual void Destroy() = 0;
175 };
176
177 /** Non-thread safe parallel task queue, executes all tasks at once in parallel. This queue type is not thread safe and
178 * should be only used from one thread.
179 */
180 class IParallelTaskQueue : public ITaskQueue {
181 public:
182 struct Deleter {
183 constexpr Deleter() noexcept = default;
operatorDeleter184 void operator()(IParallelTaskQueue* ptr) const
185 {
186 ptr->Destroy();
187 }
188 };
189 using Ptr = BASE_NS::unique_ptr<IParallelTaskQueue, Deleter>;
190
191 protected:
192 IParallelTaskQueue() = default;
193 virtual ~IParallelTaskQueue() = default;
194 IParallelTaskQueue(const IParallelTaskQueue& other) = delete;
195 virtual void Destroy() = 0;
196 };
197
198 /** Non-thread safe sequential task queue, executes tasks sequentially one-by-one. This queue type is not thread safe
199 * and should be only used from one thread. */
200 class ISequentialTaskQueue : public ITaskQueue {
201 public:
202 struct Deleter {
203 constexpr Deleter() noexcept = default;
operatorDeleter204 void operator()(ISequentialTaskQueue* ptr) const
205 {
206 ptr->Destroy();
207 }
208 };
209 using Ptr = BASE_NS::unique_ptr<ISequentialTaskQueue, Deleter>;
210
211 protected:
212 ISequentialTaskQueue() = default;
213 virtual ~ISequentialTaskQueue() = default;
214 ISequentialTaskQueue(const ISequentialTaskQueue& other) = delete;
215 virtual void Destroy() = 0;
216 };
217
218 /** Factory for creating thread pools and task queues.
219 */
220 class ITaskQueueFactory : public IInterface {
221 public:
222 static constexpr BASE_NS::Uid UID { "5b0d3810-cbcf-418a-a2e1-5df69fde1c09" };
223
224 using Ptr = BASE_NS::refcnt_ptr<ITaskQueueFactory>;
225
226 /** Get the number of concurrent threads supported by the device.
227 * @return Number of concurrent threads supported.
228 */
229 virtual uint32_t GetNumberOfCores() const = 0;
230
231 /** Create a thread safe thread pool.
232 * @param threadCount number of threads created in the pool.
233 * @return Thread pool instance.
234 */
235 virtual IThreadPool::Ptr CreateThreadPool(const uint32_t threadCount) const = 0;
236
237 /** Create a thread safe task dispatcher.
238 * @param threadPool Optional thread pool.
239 * @return Task dispatcher instance.
240 */
241 virtual IDispatcherTaskQueue::Ptr CreateDispatcherTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
242
243 /** Create a non-thread safe parallel task queue.
244 * @param threadPool Thread pool where tasks are executed in parallel.
245 * @return Parallel task queue instance.
246 */
247 virtual IParallelTaskQueue::Ptr CreateParallelTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
248
249 /** Create a non-thread safe sequential task queue.
250 * @param threadPool Optional thread pool.
251 * @return Sequential task queue instance.
252 */
253 virtual ISequentialTaskQueue::Ptr CreateSequentialTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
254
255 protected:
256 virtual ~ITaskQueueFactory() = default;
257 };
258 /** @} */
259 CORE_END_NAMESPACE()
260
261 #endif // API_CORE_THREADING_INTF_THREAD_POOL_H
262