[OpenMP][libomptarget] Add utility class for reference counting
authorKevin Sala <kevin.sala@bsc.es>
Sun, 11 Dec 2022 15:51:05 +0000 (16:51 +0100)
committerKevin Sala <kevin.sala@bsc.es>
Sun, 11 Dec 2022 20:39:25 +0000 (21:39 +0100)
The AMDGPU NextGen plugin will use this class for counting the references of some device resources.

Differential Revision: https://reviews.llvm.org/D139787

openmp/libomptarget/include/Utilities.h

index 6428c07..813ffd0 100644 (file)
@@ -19,6 +19,7 @@
 #include "Debug.h"
 
 #include <algorithm>
+#include <atomic>
 #include <cassert>
 #include <cstdint>
 #include <cstdlib>
@@ -129,6 +130,36 @@ using UInt64Envar = Envar<uint64_t>;
 using StringEnvar = Envar<std::string>;
 using BoolEnvar = Envar<bool>;
 
+/// Utility class for thread-safe reference counting. Any class that needs
+/// objects' reference counting can inherit from this entity or have it as a
+/// class data member.
+template <typename Ty = uint32_t,
+          std::memory_order MemoryOrder = std::memory_order_relaxed>
+struct RefCountTy {
+  /// Create a refcount object initialized to zero.
+  RefCountTy() : Refs(0) {}
+
+  ~RefCountTy() { assert(Refs == 0 && "Destroying with non-zero refcount"); }
+
+  /// Increase the reference count atomically.
+  void increase() { Refs.fetch_add(1, MemoryOrder); }
+
+  /// Decrease the reference count and return whether it became zero. Decreasing
+  /// the counter in more units than it was previously increased results in
+  /// undefined behavior.
+  bool decrease() {
+    Ty Prev = Refs.fetch_sub(1, MemoryOrder);
+    assert(Prev > 0 && "Invalid refcount");
+    return (Prev == 1);
+  }
+
+  Ty get() const { return Refs.load(MemoryOrder); }
+
+private:
+  /// The atomic reference counter.
+  std::atomic<Ty> Refs;
+};
+
 template <>
 inline bool StringParser::parse(const char *ValueStr, bool &Result) {
   std::string Value(ValueStr);