• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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