// Copyright 2009-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "atomic.h" namespace embree { struct NullTy { }; extern MAYBE_UNUSED NullTy null; class RefCount { public: RefCount(int val = 0) : refCounter(val) {} virtual ~RefCount() {}; virtual RefCount* refInc() { refCounter.fetch_add(1); return this; } virtual void refDec() { if (refCounter.fetch_add(-1) == 1) delete this; } private: std::atomic<size_t> refCounter; }; //////////////////////////////////////////////////////////////////////////////// /// Reference to single object //////////////////////////////////////////////////////////////////////////////// template<typename Type> class Ref { public: Type* ptr; //////////////////////////////////////////////////////////////////////////////// /// Constructors, Assignment & Cast Operators //////////////////////////////////////////////////////////////////////////////// __forceinline Ref() : ptr(nullptr) {} __forceinline Ref(NullTy) : ptr(nullptr) {} __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); } __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; } __forceinline Ref(Type* const input) : ptr(input) { if (ptr) ptr->refInc(); } __forceinline ~Ref() { if (ptr) ptr->refDec(); } __forceinline Ref& operator =(const Ref& input) { if (input.ptr) input.ptr->refInc(); if (ptr) ptr->refDec(); ptr = input.ptr; return *this; } __forceinline Ref& operator =(Ref&& input) { if (ptr) ptr->refDec(); ptr = input.ptr; input.ptr = nullptr; return *this; } __forceinline Ref& operator =(Type* const input) { if (input) input->refInc(); if (ptr) ptr->refDec(); ptr = input; return *this; } __forceinline Ref& operator =(NullTy) { if (ptr) ptr->refDec(); ptr = nullptr; return *this; } __forceinline operator bool() const { return ptr != nullptr; } __forceinline const Type& operator *() const { return *ptr; } __forceinline Type& operator *() { return *ptr; } __forceinline const Type* operator ->() const { return ptr; } __forceinline Type* operator ->() { return ptr; } template<typename TypeOut> __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); } template<typename TypeOut> __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); } template<typename TypeOut> __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); } template<typename TypeOut> __forceinline const Ref<TypeOut> dynamicCast() const { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); } }; template<typename Type> __forceinline bool operator < (const Ref<Type>& a, const Ref<Type>& b) { return a.ptr < b.ptr; } template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, NullTy ) { return a.ptr == nullptr; } template<typename Type> __forceinline bool operator ==(NullTy , const Ref<Type>& b) { return nullptr == b.ptr; } template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr == b.ptr; } template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, NullTy ) { return a.ptr != nullptr; } template<typename Type> __forceinline bool operator !=(NullTy , const Ref<Type>& b) { return nullptr != b.ptr; } template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr != b.ptr; } }