1 /*
2  * Copyright (c) 2024 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 to be executed.
94      * @param task Pointer to a task instance.
95      */
96     virtual void PushNoWait(ITask::Ptr task) = 0;
97 
98     /** Get the number of threads this pool has.
99      * @return Total number of threads in the pool.
100      */
101     virtual uint32_t GetNumberOfThreads() const = 0;
102 
103 protected:
104     virtual ~IThreadPool() = default;
105 };
106 
107 class ITaskQueue {
108 public:
109     /** Adds a task to be executed later.
110      * @param taskIdentifier Identifier for the task.
111      * @param task Pointer to a task instance.
112      */
113     virtual void Submit(uint64_t taskIdentifier, IThreadPool::ITask::Ptr&& task) = 0;
114 
115     /** Adds a task to be executed later with a dependency.
116      * @param afterIdentifier Identifier of the task that must be executed prior this task. If the identifier is
117      * unknown, the task will be added without dependency.
118      * @param taskIdentifier Identifier for the task.
119      * @param task Pointer to a task instance.
120      */
121     virtual void SubmitAfter(uint64_t afterIdentifier, uint64_t taskIdentifier, IThreadPool::ITask::Ptr&& task) = 0;
122 
123     /** Adds a task to be executed later with multiple dependencies.
124      * @param afterIdentifiers Identifiers of the tasks that must be executed prior this task. Unknown identifiers will
125      * be skipped.
126      * @param taskIdentifier Identifier for the task.
127      * @param task Pointer to a task instance.
128      */
129     virtual void SubmitAfter(BASE_NS::array_view<const uint64_t> afterIdentifiers, uint64_t taskIdentifier,
130         IThreadPool::ITask::Ptr&& task) = 0;
131 
132     /** Remove all tasks from queue. */
133     virtual void Clear() = 0;
134 
135     /** Execute tasks in queue. */
136     virtual void Execute() = 0;
137 };
138 
139 /** Thread safe task dispatcher, executes one task per execute call and removes it once it is finished.
140  */
141 class IDispatcherTaskQueue : public ITaskQueue {
142 public:
143     /** Reports finished tasks, allows to check which tasks have been completed.
144      * @return Task ids of tasks that have finished.
145      */
146     virtual BASE_NS::vector<uint64_t> CollectFinishedTasks() = 0;
147 
148     struct Deleter {
149         constexpr Deleter() noexcept = default;
operatorDeleter150         void operator()(IDispatcherTaskQueue* ptr) const
151         {
152             ptr->Destroy();
153         }
154     };
155     using Ptr = BASE_NS::unique_ptr<IDispatcherTaskQueue, Deleter>;
156 
157 protected:
158     IDispatcherTaskQueue() = default;
159     virtual ~IDispatcherTaskQueue() = default;
160     IDispatcherTaskQueue(const IDispatcherTaskQueue& other) = delete;
161     virtual void Destroy() = 0;
162 };
163 
164 /** Non-thread safe parallel task queue, executes all tasks at once in parallel. This queue type is not thread safe and
165  * should be only used from one thread.
166  */
167 class IParallelTaskQueue : public ITaskQueue {
168 public:
169     struct Deleter {
170         constexpr Deleter() noexcept = default;
operatorDeleter171         void operator()(IParallelTaskQueue* ptr) const
172         {
173             ptr->Destroy();
174         }
175     };
176     using Ptr = BASE_NS::unique_ptr<IParallelTaskQueue, Deleter>;
177 
178 protected:
179     IParallelTaskQueue() = default;
180     virtual ~IParallelTaskQueue() = default;
181     IParallelTaskQueue(const IParallelTaskQueue& other) = delete;
182     virtual void Destroy() = 0;
183 };
184 
185 /**  Non-thread safe sequential task queue, executes tasks sequentially one-by-one. This queue type is not thread safe
186  * and should be only used from one thread. */
187 class ISequentialTaskQueue : public ITaskQueue {
188 public:
189     struct Deleter {
190         constexpr Deleter() noexcept = default;
operatorDeleter191         void operator()(ISequentialTaskQueue* ptr) const
192         {
193             ptr->Destroy();
194         }
195     };
196     using Ptr = BASE_NS::unique_ptr<ISequentialTaskQueue, Deleter>;
197 
198 protected:
199     ISequentialTaskQueue() = default;
200     virtual ~ISequentialTaskQueue() = default;
201     ISequentialTaskQueue(const ISequentialTaskQueue& other) = delete;
202     virtual void Destroy() = 0;
203 };
204 
205 /** Factory for creating thread pools and task queues.
206  */
207 class ITaskQueueFactory : public IInterface {
208 public:
209     static constexpr BASE_NS::Uid UID { "5b0d3810-cbcf-418a-a2e1-5df69fde1c09" };
210 
211     using Ptr = BASE_NS::refcnt_ptr<ITaskQueueFactory>;
212 
213     /** Get the number of concurrent threads supported by the device.
214      * @return Number of concurrent threads supported.
215      */
216     virtual uint32_t GetNumberOfCores() const = 0;
217 
218     /** Create a thread safe thread pool.
219      * @param threadCount number of threads created in the pool.
220      * @return Thread pool instance.
221      */
222     virtual IThreadPool::Ptr CreateThreadPool(const uint32_t threadCount) const = 0;
223 
224     /** Create a thread safe task dispatcher.
225      * @param threadPool Optional thread pool.
226      * @return Task dispatcher instance.
227      */
228     virtual IDispatcherTaskQueue::Ptr CreateDispatcherTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
229 
230     /** Create a non-thread safe parallel task queue.
231      * @param threadPool Thread pool where tasks are executed in parallel.
232      * @return Parallel task queue instance.
233      */
234     virtual IParallelTaskQueue::Ptr CreateParallelTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
235 
236     /** Create a non-thread safe sequential task queue.
237      * @param threadPool Optional thread pool.
238      * @return Sequential task queue instance.
239      */
240     virtual ISequentialTaskQueue::Ptr CreateSequentialTaskQueue(const IThreadPool::Ptr& threadPool) const = 0;
241 
242 protected:
243     virtual ~ITaskQueueFactory() = default;
244 };
245 /** @} */
246 CORE_END_NAMESPACE()
247 
248 #endif // API_CORE_THREADING_INTF_THREAD_POOL_H
249