// Copyright 2020 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause #pragma once #include #include #include #include namespace ispcrt { class RefCounted { public: RefCounted() = default; virtual ~RefCounted() = default; RefCounted(const RefCounted &) = delete; RefCounted(RefCounted &&) = delete; RefCounted &operator=(const RefCounted &) = delete; RefCounted &operator=(RefCounted &&) = delete; void refInc() const; void refDec() const; long long useCount() const; private: mutable std::atomic refCounter{1}; }; // Inlined definitions // inline void RefCounted::refInc() const { refCounter++; } inline void RefCounted::refDec() const { if ((--refCounter) == 0) delete this; } inline long long RefCounted::useCount() const { return refCounter.load(); } ///////////////////////////////////////////////////////////////////////////// // Pointer to a RefCounted object /////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// template class IntrusivePtr { static_assert(std::is_base_of::value, "IntrusivePtr can only be used with objects derived " "from RefCounted"); public: T *ptr{nullptr}; IntrusivePtr() = default; ~IntrusivePtr(); IntrusivePtr(const IntrusivePtr &input); IntrusivePtr(IntrusivePtr &&input); template IntrusivePtr(const IntrusivePtr &input); IntrusivePtr(T *const input); IntrusivePtr &operator=(const IntrusivePtr &input); IntrusivePtr &operator=(IntrusivePtr &&input); IntrusivePtr &operator=(T *input); operator bool() const; const T &operator*() const; T &operator*(); const T *operator->() const; T *operator->(); }; // Inlined definitions // template inline IntrusivePtr::~IntrusivePtr() { if (ptr) ptr->refDec(); } template inline IntrusivePtr::IntrusivePtr(const IntrusivePtr &input) : ptr(input.ptr) { if (ptr) ptr->refInc(); } template inline IntrusivePtr::IntrusivePtr(IntrusivePtr &&input) : ptr(input.ptr) { input.ptr = nullptr; } template template inline IntrusivePtr::IntrusivePtr(const IntrusivePtr &input) : ptr(input.ptr) { if (ptr) ptr->refInc(); } template inline IntrusivePtr::IntrusivePtr(T *const input) : ptr(input) { if (ptr) ptr->refInc(); } template inline IntrusivePtr &IntrusivePtr::operator=(const IntrusivePtr &input) { if (input.ptr) input.ptr->refInc(); if (ptr) ptr->refDec(); ptr = input.ptr; return *this; } template inline IntrusivePtr &IntrusivePtr::operator=(IntrusivePtr &&input) { ptr = input.ptr; input.ptr = nullptr; return *this; } template inline IntrusivePtr &IntrusivePtr::operator=(T *input) { if (input) input->refInc(); if (ptr) ptr->refDec(); ptr = input; return *this; } template inline IntrusivePtr::operator bool() const { return ptr != nullptr; } template inline const T &IntrusivePtr::operator*() const { return *ptr; } template inline T &IntrusivePtr::operator*() { return *ptr; } template inline const T *IntrusivePtr::operator->() const { return ptr; } template inline T *IntrusivePtr::operator->() { return ptr; } // Inlined operators //////////////////////////////////////////////////////// template inline bool operator<(const IntrusivePtr &a, const IntrusivePtr &b) { return a.ptr < b.ptr; } template bool operator==(const IntrusivePtr &a, const IntrusivePtr &b) { return a.ptr == b.ptr; } template bool operator!=(const IntrusivePtr &a, const IntrusivePtr &b) { return a.ptr != b.ptr; } } // namespace ispcrt