Ocean
ScopedObject.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_SCOPED_OBJECT_H
9 #define META_OCEAN_BASE_SCOPED_OBJECT_H
10 
11 #include "ocean/base/Base.h"
12 #include "ocean/base/DataType.h"
13 
14 namespace Ocean
15 {
16 
17 /**
18  * This class wraps an unmanaged object (or reference) which needs to be released after usage.
19  * The release function can be defined at runtime.
20  * @tparam T The data type of the wrapped object
21  * @tparam TReleaseValue The optional explicit data type of the object to be released
22  * @tparam TReleaseFunction The data type of the release function
23  * @see ScopedObjectCompileTime.
24  * @ingroup base
25  */
26 template <typename T, typename TReleaseValue = T, typename TReleaseFunction = void(*)(TReleaseValue)>
28 {
29  public:
30 
31  /**
32  * Default constructor creating an object with invalid object.
33  */
34  ScopedObjectT() = default;
35 
36  /**
37  * Move constructor.
38  * @param scopedObject The scoped object to be moved
39  */
41 
42  /**
43  * Creates a new scoped object.
44  * @param object The object to be wrapped
45  * @param releaseFunction The release function
46  */
47  ScopedObjectT(T&& object, TReleaseFunction&& releaseFunction) noexcept;
48 
49  /**
50  * Creates a new scoped object.
51  * This constructor allows to decide at runtime whether the release function will be used or not.
52  * @param object The object to be wrapped
53  * @param releaseFunction The release function
54  * @param useReleaseFunction True, to use the provided release function; False, to ignore the provided release function (so that the wrapped object will never be released)
55  */
56  ScopedObjectT(T&& object, TReleaseFunction&& releaseFunction, const bool useReleaseFunction) noexcept;
57 
58  /**
59  * Creates a new scoped object.
60  * @param object The object to be wrapped
61  * @param releaseFunction The release function
62  */
63  ScopedObjectT(const T& object, TReleaseFunction&& releaseFunction) noexcept;
64 
65  /**
66  * Creates a new scoped object.
67  * This constructor allows to decide at runtime whether the release function will be used or not.
68  * @param object The object to be wrapped
69  * @param releaseFunction The release function
70  * @param useReleaseFunction True, to use the provided release function; False, to ignore the provided release function (so that the wrapped object will never be released)
71  */
72  ScopedObjectT(const T& object, TReleaseFunction&& releaseFunction, const bool useReleaseFunction) noexcept;
73 
74  /**
75  * Destructs this scoped object and releases the internal wrapped object.
76  */
78 
79  /**
80  * Returns whether this scoped object holds a valid release function (which will be invoked once the object is released).
81  * @return True, if so
82  */
83  bool isValid() const;
84 
85  /**
86  * Returns the wrapped object.
87  * @return The wrapped object
88  */
89  const T& object() const;
90 
91  /**
92  * Arrow operator returning the wrapped object.
93  * Ensure that the object is valid before calling this operator.
94  * @return The wrapped object
95  * @see isValid().
96  */
97  const T& operator->() const;
98 
99  /**
100  * De-reference operator returning the wrapped object.
101  * Ensure that the object is valid before calling this operator.
102  * @return The wrapped object
103  * @see isValid().
104  */
105  const T& operator*() const;
106 
107  /**
108  * Explicitly releases the wrapped object.
109  */
110  void release();
111 
112  /**
113  * Move operator.
114  * @param scopedObject The scoped object to be moved
115  * @return Reference to this object
116  */
118 
119 #ifdef OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
120 
121  /**
122  * Returns the wrapped object.
123  * @return The wrapped object
124  */
125  operator const T&() const;
126 
127 #endif // OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
128 
129  protected:
130 
131  /**
132  * Disabled copy constructor.
133  */
135 
136  /**
137  * Disabled assign operator.
138  * @return Reference to this object
139  */
141 
142  protected:
143 
144  /// The wrapped reference.
145  T object_ = T();
146 
147  /// The function used to release the wrapped object.
148  TReleaseFunction releaseFunction_ = TReleaseFunction();
149 };
150 
151 /**
152  * This class wraps an unmanaged object (or reference) which needs to be released after usage.
153  * The release function needs to be defined at compile time.
154  * @tparam T The data type of the wrapped object
155  * @tparam TReleaseValue The optional explicit data type of the object to be released
156  * @tparam TReleaseReturn The data type of the return value of the release function
157  * @tparam tReleaseFunction The data type of the release function
158  * @tparam tExpectedReturnValue The expected return value of the release function
159  * @tparam tCheckReturnValue True, to check the return value when calling the release function; False, to ignore the return value
160  * @tparam tInvalidValue The value of an invalid object
161  * @see ScopedObjectT.
162  * @ingroup base
163  */
164 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue = NotVoidTyper<TReleaseReturn>::defaultValue(), bool tCheckReturnValue = true, T tInvalidValue = T()>
166 {
167  public:
168 
169  /**
170  * Default constructor creating an object with invalid object.
171  */
173 
174  /**
175  * Move constructor.
176  * @param scopedObject The scoped object to be moved
177  */
179 
180  /**
181  * Creates a new scoped object.
182  * If 'object == tInvalidValue' the object will not be released once this scoped object is disposed.
183  * @param object The object to be wrapped
184  */
185  explicit ScopedObjectCompileTimeT(T&& object) noexcept;
186 
187  /**
188  * Creates a new scoped object.
189  * @param object The object to be wrapped
190  * @param needsRelease True, if the given object needs to be released once the scoped object is disposed; False, if the given object does not need to be released
191  */
192  ScopedObjectCompileTimeT(T&& object, const bool needsRelease) noexcept;
193 
194  /**
195  * Creates a new scoped object.
196  * If 'object == tInvalidValue' the object will not be released once this scoped object is disposed.
197  * @param object The object to be wrapped
198  */
199  explicit ScopedObjectCompileTimeT(const T& object);
200 
201  /**
202  * Creates a new scoped object.
203  * @param object The object to be wrapped
204  * @param needsRelease True, if the given object needs to be released once the scoped object is disposed; False, if the given object does not need to be released
205  */
206  ScopedObjectCompileTimeT(const T& object, const bool needsRelease);
207 
208  /**
209  * Destructs this scoped object and releases the internal wrapped object.
210  */
212 
213  /**
214  * Returns whether this scoped object holds a valid object.
215  * @return True, if so
216  */
217  bool isValid() const;
218 
219  /**
220  * Returns the wrapped object.
221  * @return The wrapped object
222  */
223  const T& object() const;
224 
225  /**
226  * Returns the wrapped object.
227  * Ensure that the object is valid before calling this operator.
228  * @return The wrapped object
229  * @see isValid().
230  */
231  const T& operator->() const;
232 
233  /**
234  * De-reference operator returning the wrapped object.
235  * Ensure that the object is valid before calling this operator.
236  * @return The wrapped object
237  * @see isValid().
238  */
239  const T& operator*() const;
240 
241  /**
242  * Releases the current wrapped object and returns a new wrapped object.
243  * @param needsRelease True, if the new object needs to be released once the scoped object is disposed; False, if the new object does not need to be released
244  * @return The new wrapped object
245  */
246  T& resetObject(const bool needsRelease = true);
247 
248  /**
249  * Explicitly releases the wrapped object.
250  */
251  void release();
252 
253  /**
254  * Move operator.
255  * @param scopedObject The scoped object to be moved
256  * @return Reference to this object
257  */
259 
260 #ifdef OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
261 
262  /**
263  * Returns the wrapped object.
264  * @return The wrapped object
265  */
266  operator const T&() const;
267 
268 #endif // OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
269 
270  protected:
271 
272  /**
273  * Disabled copy constructor.
274  */
276 
277  /**
278  * Disabled assign operator.
279  * @return Reference to this object
280  */
282 
283  protected:
284 
285  /// The wrapped reference.
286  T object_ = tInvalidValue;
287 
288  /// True, if the wrapped object needs to be released.
289  bool needsRelease_ = false;
290 };
291 
292 /**
293  * Template specialization for ScopedObjectCompileTimeT with void return value.
294  * @tparam T The data type of the wrapped object
295  * @tparam tReleaseFunction The data type of the release function
296  * @see ScopedObjectCompileTimeT.
297  * @ingroup base
298  */
299 template <typename T, void (*tReleaseFunction)(T)>
301 
302 template <typename T, typename TReleaseValue, typename TReleaseFunction>
304 {
305  *this = std::move(scopedObject);
306 }
307 
308 template <typename T, typename TReleaseValue, typename TReleaseFunction>
309 ScopedObjectT<T, TReleaseValue, TReleaseFunction>::ScopedObjectT(T&& object, TReleaseFunction&& releaseFunction) noexcept :
310  object_(std::move(object)),
311  releaseFunction_(std::move(releaseFunction))
312 {
313  // nothing to do here
314 }
315 
316 template <typename T, typename TReleaseValue, typename TReleaseFunction>
317 ScopedObjectT<T, TReleaseValue, TReleaseFunction>::ScopedObjectT(T&& object, TReleaseFunction&& releaseFunction, const bool useReleaseFunction) noexcept :
318  object_(std::move(object))
319 {
320  if (useReleaseFunction)
321  {
322  releaseFunction_ = std::move(releaseFunction);
323  }
324 }
325 
326 template <typename T, typename TReleaseValue, typename TReleaseFunction>
327 ScopedObjectT<T, TReleaseValue, TReleaseFunction>::ScopedObjectT(const T& object, TReleaseFunction&& releaseFunction) noexcept :
328  object_(object),
329  releaseFunction_(std::move(releaseFunction))
330 {
331  // nothing to do here
332 }
333 
334 template <typename T, typename TReleaseValue, typename TReleaseFunction>
335 ScopedObjectT<T, TReleaseValue, TReleaseFunction>::ScopedObjectT(const T& object, TReleaseFunction&& releaseFunction, const bool useReleaseFunction) noexcept :
336  object_(object)
337 {
338  if (useReleaseFunction)
339  {
340  releaseFunction_ = std::move(releaseFunction);
341  }
342 }
343 
344 template <typename T, typename TReleaseValue, typename TReleaseFunction>
346 {
347  release();
348 }
349 
350 template <typename T, typename TReleaseValue, typename TReleaseFunction>
352 {
353  return bool(releaseFunction_);
354 }
355 
356 template <typename T, typename TReleaseValue, typename TReleaseFunction>
358 {
359  return object_;
360 }
361 
362 template <typename T, typename TReleaseValue, typename TReleaseFunction>
364 {
365  ocean_assert(isValid());
366 
367  return object();
368 }
369 
370 template <typename T, typename TReleaseValue, typename TReleaseFunction>
372 {
373  ocean_assert(isValid());
374 
375  return object();
376 }
377 
378 template <typename T, typename TReleaseValue, typename TReleaseFunction>
380 {
381  if (releaseFunction_)
382  {
383  releaseFunction_(TReleaseValue(object_));
384 
385  object_ = T();
386  releaseFunction_ = TReleaseFunction();
387  }
388 }
389 
390 template <typename T, typename TReleaseValue, typename TReleaseFunction>
392 {
393  if (this != &scopedObject)
394  {
395  release();
396 
397  object_ = std::move(scopedObject.object_);
398  scopedObject.object_ = T();
399 
400  releaseFunction_ = std::move(scopedObject.releaseFunction_);
401  scopedObject.releaseFunction_ = TReleaseFunction();
402  }
403 
404  return *this;
405 }
406 
407 #ifdef OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
408 
409 template <typename T, typename TReleaseValue, typename TReleaseFunction>
411 {
412  return object_;
413 }
414 
415 #endif
416 
417 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
419 {
420  *this = std::move(scopedObject);
421 }
422 
423 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
425  object_(std::move(object))
426 {
427  needsRelease_ = object_ != tInvalidValue;
428 }
429 
430 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
432  object_(std::move(object)),
433  needsRelease_(needsRelease)
434 {
435  // nothing to do here
436 }
437 
438 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
440  object_(object)
441 {
442  needsRelease_ = object_ != tInvalidValue;
443 }
444 
445 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
447  object_(object),
448  needsRelease_(needsRelease)
449 {
450  // nothing to do here
451 }
452 
453 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
455 {
456  release();
457 }
458 
459 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
461 {
462  return object_ != tInvalidValue;
463 }
464 
465 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
467 {
468  return object_;
469 }
470 
471 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
473 {
474  ocean_assert(isValid());
475 
476  return object();
477 }
478 
479 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
481 {
482  ocean_assert(isValid());
483 
484  return object();
485 }
486 
487 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
489 {
490  release();
491  object_ = tInvalidValue;
492 
493  needsRelease_ = needsRelease;
494 
495  return object_;
496 }
497 
498 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
500 {
501  if (needsRelease_)
502  {
503  if constexpr (std::is_same<TReleaseReturn, void>::value)
504  {
505  tReleaseFunction(TReleaseValue(object_));
506  }
507  else
508  {
509  if constexpr (tCheckReturnValue)
510  {
511  const TReleaseReturn returnValue = tReleaseFunction(TReleaseValue(object_));
512  ocean_assert_and_suppress_unused(returnValue == tExpectedReturnValue, returnValue);
513  }
514  else
515  {
516  const TReleaseReturn returnValue = tReleaseFunction(TReleaseValue(object_));
517  OCEAN_SUPPRESS_UNUSED_WARNING(returnValue);
518  }
519  }
520 
521  object_ = tInvalidValue;
522  needsRelease_ = false;
523  }
524 }
525 
526 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
528 {
529  if (this != &scopedObject)
530  {
531  release();
532 
533  object_ = std::move(scopedObject.object_);
534  scopedObject.object_ = tInvalidValue;
535 
536  needsRelease_ = scopedObject.needsRelease_;
537  scopedObject.needsRelease_ = false;
538  }
539 
540  return *this;
541 }
542 
543 #ifdef OCEAN_ENABLE_CAST_OPERATOR_FOR_SCOPED_OBJECT
544 
545 template <typename T, typename TReleaseValue, typename TReleaseReturn, TReleaseReturn (*tReleaseFunction)(TReleaseValue), typename NotVoidTyper<TReleaseReturn>::Type tExpectedReturnValue, bool tCheckReturnValue, T tInvalidValue>
547 {
548  return object_;
549 }
550 
551 #endif
552 
553 }
554 
555 #endif // META_OCEAN_BASE_SCOPED_OBJECT_H
This class wraps an unmanaged object (or reference) which needs to be released after usage.
Definition: ScopedObject.h:166
bool needsRelease_
True, if the wrapped object needs to be released.
Definition: ScopedObject.h:289
ScopedObjectCompileTimeT & operator=(const ScopedObjectCompileTimeT< T, TReleaseValue, TReleaseReturn, tReleaseFunction, tExpectedReturnValue, tCheckReturnValue, tInvalidValue > &)=delete
Disabled assign operator.
ScopedObjectCompileTimeT(T &&object, const bool needsRelease) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:431
bool isValid() const
Returns whether this scoped object holds a valid object.
Definition: ScopedObject.h:460
ScopedObjectCompileTimeT(T &&object) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:424
ScopedObjectCompileTimeT(const T &object, const bool needsRelease)
Creates a new scoped object.
Definition: ScopedObject.h:446
ScopedObjectCompileTimeT()=default
Default constructor creating an object with invalid object.
const T & object() const
Returns the wrapped object.
Definition: ScopedObject.h:466
ScopedObjectCompileTimeT(const ScopedObjectCompileTimeT< T, TReleaseValue, TReleaseReturn, tReleaseFunction, tExpectedReturnValue, tCheckReturnValue, tInvalidValue > &)=delete
Disabled copy constructor.
void release()
Explicitly releases the wrapped object.
Definition: ScopedObject.h:499
ScopedObjectCompileTimeT< T, TReleaseValue, TReleaseReturn, tReleaseFunction, tExpectedReturnValue, tCheckReturnValue, tInvalidValue > & operator=(ScopedObjectCompileTimeT< T, TReleaseValue, TReleaseReturn, tReleaseFunction, tExpectedReturnValue, tCheckReturnValue, tInvalidValue > &&scopedObject) noexcept
Move operator.
Definition: ScopedObject.h:527
T object_
The wrapped reference.
Definition: ScopedObject.h:286
const T & operator*() const
De-reference operator returning the wrapped object.
Definition: ScopedObject.h:480
ScopedObjectCompileTimeT(ScopedObjectCompileTimeT< T, TReleaseValue, TReleaseReturn, tReleaseFunction, tExpectedReturnValue, tCheckReturnValue, tInvalidValue > &&scopedObject) noexcept
Move constructor.
Definition: ScopedObject.h:418
~ScopedObjectCompileTimeT()
Destructs this scoped object and releases the internal wrapped object.
Definition: ScopedObject.h:454
ScopedObjectCompileTimeT(const T &object)
Creates a new scoped object.
Definition: ScopedObject.h:439
T & resetObject(const bool needsRelease=true)
Releases the current wrapped object and returns a new wrapped object.
Definition: ScopedObject.h:488
const T & operator->() const
Returns the wrapped object.
Definition: ScopedObject.h:472
This class wraps an unmanaged object (or reference) which needs to be released after usage.
Definition: ScopedObject.h:28
ScopedObjectT(T &&object, TReleaseFunction &&releaseFunction) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:309
ScopedObjectT< T, TReleaseValue, TReleaseFunction > & operator=(const ScopedObjectT< T, TReleaseValue, TReleaseFunction > &)=delete
Disabled assign operator.
ScopedObjectT(T &&object, TReleaseFunction &&releaseFunction, const bool useReleaseFunction) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:317
T object_
The wrapped reference.
Definition: ScopedObject.h:145
const T & operator*() const
De-reference operator returning the wrapped object.
Definition: ScopedObject.h:371
void release()
Explicitly releases the wrapped object.
Definition: ScopedObject.h:379
~ScopedObjectT()
Destructs this scoped object and releases the internal wrapped object.
Definition: ScopedObject.h:345
ScopedObjectT(const T &object, TReleaseFunction &&releaseFunction, const bool useReleaseFunction) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:335
TReleaseFunction releaseFunction_
The function used to release the wrapped object.
Definition: ScopedObject.h:148
ScopedObjectT()=default
Default constructor creating an object with invalid object.
const T & operator->() const
Arrow operator returning the wrapped object.
Definition: ScopedObject.h:363
ScopedObjectT< T, TReleaseValue, TReleaseFunction > & operator=(ScopedObjectT< T, TReleaseValue, TReleaseFunction > &&scopedObject) noexcept
Move operator.
Definition: ScopedObject.h:391
ScopedObjectT(const ScopedObjectT< T, TReleaseValue, TReleaseFunction > &)=delete
Disabled copy constructor.
bool isValid() const
Returns whether this scoped object holds a valid release function (which will be invoked once the obj...
Definition: ScopedObject.h:351
const T & object() const
Returns the wrapped object.
Definition: ScopedObject.h:357
ScopedObjectT(ScopedObjectT< T, TReleaseValue, TReleaseFunction > &&scopedObject) noexcept
Move constructor.
Definition: ScopedObject.h:303
ScopedObjectT(const T &object, TReleaseFunction &&releaseFunction) noexcept
Creates a new scoped object.
Definition: ScopedObject.h:327
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