説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

AtomicReferenceCounter.h 3.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #pragma once
  2. #include "Atomic.h"
  3. #include "../C/Baselib_Atomic_TypeSafe.h"
  4. namespace baselib
  5. {
  6. BASELIB_CPP_INTERFACE
  7. {
  8. // Atomic Reference counter.
  9. // Provides a decrement that has release barrier semantics and acquire-release if the reference count reaches zero.
  10. // Increment does NOT provide any memory synchronization!
  11. //
  12. // This is useful for ensuring that no reads/writes are happening on a deleted object (i.e. on memory that may be reclaimed!)
  13. // By issuing a release barrier on every reference decrement, we ensure that no loads or reads are reordered after the decrement.
  14. // The acquire barrier on reaching zero then ensure that operations before previous decrement-releases are finished and
  15. // that any following memory reclaiming actions will not happen before the final release.
  16. struct atomic_reference_counter
  17. {
  18. atomic_reference_counter(int32_t initialValue = 0) : referenceCount(initialValue) {}
  19. atomic_reference_counter(const atomic_reference_counter& other) = delete;
  20. atomic_reference_counter& operator=(const atomic_reference_counter& other) = delete;
  21. atomic_reference_counter(atomic_reference_counter&& other) = delete;
  22. atomic_reference_counter& operator=(const atomic_reference_counter&& other) = delete;
  23. // Underlying counter. Direct access should only be necessary in exceptional cases!
  24. baselib::atomic<int32_t> referenceCount;
  25. // Decrements a reference counter with acquire-release memory-barrier if value reaches 0, otherwise release.
  26. // Returns true if operation caused counter to reach 0, false otherwise.
  27. // Note that we intentionally only overload the pre-decrement, as the semantics of post increment aren't entirely clear.
  28. FORCE_INLINE bool operator--() { return Baselib_atomic_ref_dec_32(&referenceCount.obj); }
  29. // Increments a reference counter by 1 relaxed memory barrier semantics.
  30. // Returns true if the reference counter was 0 prior to incrementing
  31. FORCE_INLINE bool operator++() { return referenceCount.fetch_add(1, baselib::memory_order_relaxed) == 0; }
  32. // Increments a reference counter by 1 relaxed memory barrier semantics.
  33. // Returns true if the reference counter was 0 prior to incrementing
  34. FORCE_INLINE bool operator++(int) { return referenceCount.fetch_add(1, baselib::memory_order_relaxed) == 0; }
  35. // Increments a reference counter by 1 relaxed memory barrier semantics.
  36. // Returns true if the reference counter was 0 prior to incrementing
  37. FORCE_INLINE bool acquire() { return referenceCount.fetch_add(1, baselib::memory_order_relaxed) == 0; }
  38. // Decrements a reference counter with acquire-release memory-barrier if value reaches 0, otherwise release.
  39. // Returns true if operation caused counter to reach 0, false otherwise.
  40. FORCE_INLINE bool release() { return Baselib_atomic_ref_dec_32(&referenceCount.obj); }
  41. };
  42. }
  43. }