Ocean
WorkerPool.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_WORKER_POOL_H
9 #define META_OCEAN_BASE_WORKER_POOL_H
10 
11 #include "ocean/base/Base.h"
12 #include "ocean/base/Lock.h"
13 #include "ocean/base/Singleton.h"
15 #include "ocean/base/Worker.h"
16 
17 namespace Ocean
18 {
19 
20 /**
21  * This class implements a pool holding worker objects for individual use.
22  * @see Worker.
23  * @ingroup base
24  */
25 class OCEAN_BASE_EXPORT WorkerPool : public Singleton<WorkerPool>
26 {
27  friend class Singleton<WorkerPool>;
28  friend class ScopedWorker;
29 
30  private:
31 
32  /**
33  * Definition of a unique pointer holding a Worker object.
34  */
35  using UniqueWorker = std::unique_ptr<Worker>;
36 
37  /**
38  * Definition of a static vector holding worker objects.
39  */
41 
42  public:
43 
44  /**
45  * Definition of scoped worker object.
46  */
47  class OCEAN_BASE_EXPORT ScopedWorker
48  {
49  public:
50 
51  /**
52  * Creates an empty scoped worker object.
53  */
54  ScopedWorker() = default;
55 
56  /**
57  * Move constructor.
58  * @param object The object to move
59  */
60  inline ScopedWorker(ScopedWorker&& object) noexcept;
61 
62  /**
63  * Creates a new scoped worker object.
64  * @param worker The worker object of this scoped object.
65  */
66  explicit inline ScopedWorker(Worker* worker) noexcept;
67 
68  /**
69  * Destructs a scoped worker object and unlocks the internal worker object automatically.
70  */
71  inline ~ScopedWorker();
72 
73  /**
74  * Returns the internal worker object.
75  * Beware: Do not store this object outside this scoped object.
76  * The internal object will exist as long this scoped objects exist.
77  * @return Worker object of this scoped object
78  */
79  inline Worker* worker() const;
80 
81  /**
82  * Explicitly releases the object and does not wait until the scope ends.
83  * The internal worker object will be returned to the worker pool and cannot be accessed anymore by this object.
84  */
85  inline void release();
86 
87  /**
88  * Move a scoped worker object.
89  * @param object The object to move
90  * @return Reference to this object
91  */
92  inline ScopedWorker& operator=(ScopedWorker&& object) noexcept;
93 
94  /**
95  * Returns the internal worker object.
96  * Beware: Do not store this object outside this scoped object.
97  * The internal object will exist as long this scoped objects exist.
98  * @return Worker object of this scoped object
99  */
100  inline Worker* operator()() const;
101 
102  /**
103  * Returns whether this scoped objects holds an internal worker object.
104  * @return True, if so
105  */
106  explicit inline operator bool() const;
107 
108  private:
109 
110  /**
111  * Disabled copy constructor.
112  * @param scopedWorker Object which would be copied
113  */
114  ScopedWorker(const ScopedWorker& scopedWorker) = delete;
115 
116  /**
117  * Disabled copy operator.
118  * @param scopedWorker Object which would be copied
119  * @return Reference to this object
120  */
121  ScopedWorker& operator=(const ScopedWorker& scopedWorker) = delete;
122 
123  private:
124 
125  /// Internal worker object.
126  Worker* worker_ = nullptr;
127  };
128 
129  public:
130 
131  /**
132  * Returns the maximal number of worker objects allowed inside this pool.
133  * @return Maximal worker capacity, with range [1, 10], 2 by default
134  */
135  inline size_t capacity();
136 
137  /**
138  * Returns the number of currently existing worker objects in this pool.
139  * @return Worker count, with range [0, capacity()]
140  */
141  inline size_t size();
142 
143  /**
144  * Defines the maximal number of worker objects existing concurrently.
145  * @param workers Maximal number of worker objects to be allowed inside this pool, with range [capacity(), 10]
146  * @return True, if succeeded
147  */
148  bool setCapacity(const size_t workers);
149 
150  /**
151  * Returns a scoped object holding the real worker if available.
152  * The scoped object guarantees the existence of the real worker (if available in the moment this function is called) as long as the scoped object exists.
153  * @return Object holding the worker if available, otherwise the object will be empty
154  */
156 
157  /**
158  * Returns a scoped object holding the real worker if a given condition is 'True' and if a worker is available.
159  * The scoped object guarantees the existence of the real worker (if provided in the moment this function is called) as long as the scoped object exists.<br>
160  * This function allows to apply something like:
161  * @code
162  * // we invoke the following function in a single-core manner for small images (< 400 * 400 pixels),
163  * // and in a multi-core manner for large images
164  * invokeMulticoreFunction(frame, WorkerPool::get().conditionalScopedWorker(frame.pixels() >= 400u * 400u)());
165  * @endcode
166  * @param condition True, to get a scoped worker with real worker object (if available); False, to get an empty scoped worker
167  * @return Object holding the worker if available, otherwise the object will be empty
168  */
169  inline ScopedWorker conditionalScopedWorker(const bool condition);
170 
171  private:
172 
173  /**
174  * Creates a new worker pool and initializes the maximal worker capacity to 2.
175  */
176  WorkerPool() = default;
177 
178  /**
179  * Destructs a worker pool.
180  */
182 
183  /**
184  * Tries to lock a worker to be used for individual worker.
185  * Beware: This worker object must be unlocked after usage.
186  * @return Worker object if available, otherwise nullptr
187  * @see unlock().
188  */
190 
191  /**
192  * Unlocks a previously locked worker object to make it available for other users.
193  * Beware: To not use an unlocked worker object anymore.
194  * @param worker The worker to be unlocked
195  */
196  void unlock(Worker* worker);
197 
198  private:
199 
200  /// Vector holding the currently not-used worker objects.
202 
203  /// Vector holding the currently used worker objects.
205 
206  /// Maximal pool capacity, with range [1, infinity)
207  size_t capacity_ = 2;
208 
209  /// Lock for the entire pool.
211 };
212 
214 {
215  *this = std::move(object);
216 }
217 
219  worker_(worker)
220 {
221  // nothing to do here
222 }
223 
225 {
226  release();
227 }
228 
230 {
231  return worker_;
232 }
233 
235 {
236  if (worker_ != nullptr)
237  {
238  WorkerPool::get().unlock(worker_);
239  worker_ = nullptr;
240  }
241 }
242 
244 {
245  if (this != &object)
246  {
247  release();
248 
249  worker_ = object.worker_;
250  object.worker_ = nullptr;
251  }
252 
253  return *this;
254 }
255 
257 {
258  return worker_;
259 }
260 
261 inline WorkerPool::ScopedWorker::operator bool() const
262 {
263  return worker_ != nullptr;
264 }
265 
266 inline size_t WorkerPool::capacity()
267 {
268  const ScopedLock scopedLock(lock_);
269 
270  return capacity_;
271 }
272 
273 inline size_t WorkerPool::size()
274 {
275  const ScopedLock scopedLock(lock_);
276 
277  return usedWorkers_.size() + freeWorkers_.size();
278 }
279 
281 {
282  if (condition)
283  {
284  return scopedWorker();
285  }
286  else
287  {
288  return ScopedWorker();
289  }
290 }
291 
292 }
293 
294 #endif // META_OCEAN_BASE_WORKER_POOL_H
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
This template class is the base class for all singleton objects.
Definition: Singleton.h:71
static WorkerPool & get()
Returns a reference to the unique object.
Definition: Singleton.h:115
size_t size() const
Returns the size of this vector.
Definition: StaticVector.h:340
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
Definition of scoped worker object.
Definition: WorkerPool.h:48
ScopedWorker & operator=(ScopedWorker &&object) noexcept
Move a scoped worker object.
Definition: WorkerPool.h:243
ScopedWorker(const ScopedWorker &scopedWorker)=delete
Disabled copy constructor.
Worker * operator()() const
Returns the internal worker object.
Definition: WorkerPool.h:256
Worker * worker() const
Returns the internal worker object.
Definition: WorkerPool.h:229
ScopedWorker & operator=(const ScopedWorker &scopedWorker)=delete
Disabled copy operator.
~ScopedWorker()
Destructs a scoped worker object and unlocks the internal worker object automatically.
Definition: WorkerPool.h:224
ScopedWorker()=default
Creates an empty scoped worker object.
void release()
Explicitly releases the object and does not wait until the scope ends.
Definition: WorkerPool.h:234
This class implements a pool holding worker objects for individual use.
Definition: WorkerPool.h:26
Worker * lock()
Tries to lock a worker to be used for individual worker.
bool setCapacity(const size_t workers)
Defines the maximal number of worker objects existing concurrently.
Workers freeWorkers_
Vector holding the currently not-used worker objects.
Definition: WorkerPool.h:201
size_t capacity()
Returns the maximal number of worker objects allowed inside this pool.
Definition: WorkerPool.h:266
size_t capacity_
Maximal pool capacity, with range [1, infinity)
Definition: WorkerPool.h:207
Lock lock_
Lock for the entire pool.
Definition: WorkerPool.h:210
ScopedWorker scopedWorker()
Returns a scoped object holding the real worker if available.
void unlock(Worker *worker)
Unlocks a previously locked worker object to make it available for other users.
~WorkerPool()
Destructs a worker pool.
size_t size()
Returns the number of currently existing worker objects in this pool.
Definition: WorkerPool.h:273
Workers usedWorkers_
Vector holding the currently used worker objects.
Definition: WorkerPool.h:204
friend class ScopedWorker
Definition: WorkerPool.h:28
ScopedWorker conditionalScopedWorker(const bool condition)
Returns a scoped object holding the real worker if a given condition is 'True' and if a worker is ava...
Definition: WorkerPool.h:280
WorkerPool()=default
Creates a new worker pool and initializes the maximal worker capacity to 2.
std::unique_ptr< Worker > UniqueWorker
Definition of a unique pointer holding a Worker object.
Definition: WorkerPool.h:35
void release(T *object)
This functions allows to release a DirectShow object if it does exist.
Definition: DSObject.h:266
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15