182using RefCountType = std::atomic<long>;
184inline long ref_count_increment(RefCountType& count)
noexcept {
return count.fetch_add(1L, std::memory_order_seq_cst); }
188 return count.fetch_add(-1L, std::memory_order_seq_cst);
204 RefCountType ref_count_;
216 CHOLLA_ASSERT(preincrement_val >= 1L,
"invariant is violated");
223 CHOLLA_ASSERT(predecrement_val > 0L,
"invariant is violated");
224 if (predecrement_val == 1L)
delete this;
228template <
typename HandleOrPtrType,
typename Deleter>
231 HandleOrPtrType managed_;
250#if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)
251 #define CALL_INCREMENT_COUNT(cb_ptr)
252 #define CALL_DECREMENT_COUNT(cb_ptr)
254 #define CALL_INCREMENT_COUNT(cb_ptr) (cb_ptr)->increment_count()
255 #define CALL_DECREMENT_COUNT(cb_ptr) (cb_ptr)->decrement_count()
267#define DEFINE_COMMON_METHODS(KLASS) \
276 template <typename T> \
277 __host__ __device__ KLASS<T>::KLASS(const KLASS<T>& other) noexcept : wrapped_{other.wrapped_}, cb_{other.cb_} \
279 if (cb_ != nullptr) { \
285 CALL_INCREMENT_COUNT(cb_); \
291 template <typename T> \
292 __host__ __device__ KLASS<T>::KLASS(KLASS<T>&& other) noexcept : wrapped_{other.wrapped_}, cb_{other.cb_} \
294 other.set_empty_wrapped_(); \
295 other.cb_ = nullptr; \
299 template <typename T> \
300 __host__ __device__ KLASS<T>& KLASS<T>::operator=(const KLASS<T>& other) noexcept \
307 if (this == &other) return *this; \
312 bool different_control_blocks = cb_ != other.cb_; \
313 if (different_control_blocks and (other.cb_ != nullptr)) CALL_INCREMENT_COUNT(other.cb_); \
314 if (different_control_blocks and (cb_ != nullptr)) CALL_DECREMENT_COUNT(cb_); \
316 wrapped_ = other.wrapped_; \
321 template <typename T> \
322 __host__ __device__ KLASS<T>& KLASS<T>::operator=(KLASS<T>&& other) noexcept \
329 template <typename T> \
330 __host__ __device__ void KLASS<T>::swap(KLASS<T>& other) noexcept \
332 decltype(wrapped_) tmp_wrapped = wrapped_; \
333 wrapped_ = other.wrapped_; \
334 other.wrapped_ = tmp_wrapped; \
336 detail::ControlBlock* tmp_cb = cb_; \
338 other.cb_ = tmp_cb; \
341 template <typename T> \
342 __host__ __device__ void KLASS<T>::reset() noexcept \
348 if (cb_ != nullptr) { \
350 CALL_DECREMENT_COUNT(cb_); \
353 set_empty_wrapped_(); \
365template <
typename HandleT>
369 static_assert(std::is_arithmetic_v<HandleT> or std::is_aggregate_v<HandleT> or std::is_pointer_v<HandleT>);
370 static_assert(not std::is_const_v<HandleT>);
381 __host__ __device__ __forceinline__
void set_empty_wrapped_()
const noexcept {}
385 typedef HandleT wrapped_ref_type;
410 template <
typename Deleter>
413 : wrapped_{handle}, cb_{new detail::ControlBlockImpl<HandleT, Deleter>(handle, d)}
433 __host__ __device__
void reset() noexcept;
436 __host__ __device__ __forceinline__ HandleT
get() const noexcept {
return wrapped_; }
439 __host__ __device__
explicit operator bool() const noexcept {
return cb_ !=
nullptr; }
459 __host__ __device__ __forceinline__
void set_empty_wrapped_()
noexcept { wrapped_ =
nullptr; }
463 typedef T* wrapped_ref_type;
466 __host__ __device__
SharedDevPtr() : wrapped_{nullptr}, cb_{nullptr} {}
481 template <
typename Deleter>
484 : wrapped_{ptr}, cb_{new detail::ControlBlockImpl<T*, Deleter>(ptr, d)}
504 __host__ __device__
void reset() noexcept;
507 __host__ __device__ __forceinline__ T*
get() const noexcept {
return wrapped_; }
510 __host__ __device__
explicit operator bool() const noexcept {
return wrapped_ !=
nullptr; }
519 __device__ __forceinline__ T&
operator*() const noexcept {
return *wrapped_; }
529 __device__ __forceinline__ T&
operator[](std::ptrdiff_t idx)
const {
return wrapped_[idx]; }
536#undef CALL_INCREMENT_COUNT
537#undef CALL_DECREMENT_COUNT
538#undef DEFINE_COMMON_METHODS
Wraps a device pointer while providing shared object semantics.
Definition shared.h:452
__host__ __device__ SharedDevPtr()
Default constructor (creates an "empty" instance)
Definition shared.h:466
__host__ __device__ ~SharedDevPtr() noexcept
Destructor.
Definition shared.h:489
__device__ __forceinline__ T & operator*() const noexcept
Dereference the stored pointer.
Definition shared.h:519
__host__ SharedDevPtr(T *ptr, Deleter d)
Primary constructor.
Definition shared.h:482
__host__ __device__ void swap(SharedDevPtr &other) noexcept
swap the contents of this and other
__device__ __forceinline__ T & operator[](std::ptrdiff_t idx) const
Dereference the stored pointer.
Definition shared.h:529
__host__ __device__ __forceinline__ T * get() const noexcept
Return the stored pointer.
Definition shared.h:507
__host__ __device__ void reset() noexcept
Release ownership of the owned resource (if any)
Wraps a handles while providing shared object semantics.
Definition shared.h:367
__host__ SharedHandle(HandleT handle, Deleter d)
Primary constructor.
Definition shared.h:411
__host__ __device__ void swap(SharedHandle &o) noexcept
swap the contents of this and other
__host__ __device__ __forceinline__ HandleT get() const noexcept
Return the stored handle.
Definition shared.h:436
__host__ __device__ ~SharedHandle() noexcept
Destructor.
Definition shared.h:418
__host__ __device__ void reset() noexcept
Release ownership of the owned resource (if any)
__host__ __device__ SharedHandle()
Default Constructor (constructs an empty instance)
Definition shared.h:395
Helps implement SharedHandle & SharedDevPtr.
Definition shared.h:203
void increment_count() noexcept
increment reference count
Definition shared.h:213
void decrement_count() noexcept
decrement ref count & trigger destructor of this if the count hits 0
Definition shared.h:220
#define DEFINE_COMMON_METHODS(KLASS)
Implements common methods of SharedHandle and SharedDevPtr.
Definition shared.h:267
long ref_count_increment(RefCountType &count) noexcept
Definition shared.h:184
long ref_count_decrement(RefCountType &count) noexcept
Definition shared.h:186