1 // Copyright 2009-2021 Intel Corporation 2 // SPDX-License-Identifier: Apache-2.0 3 4 #pragma once 5 6 #include "atomic.h" 7 8 namespace embree 9 { 10 struct NullTy { 11 }; 12 13 extern MAYBE_UNUSED NullTy null; 14 15 class RefCount 16 { 17 public: refCounter(val)18 RefCount(int val = 0) : refCounter(val) {} ~RefCount()19 virtual ~RefCount() {}; 20 refInc()21 virtual RefCount* refInc() { refCounter.fetch_add(1); return this; } refDec()22 virtual void refDec() { if (refCounter.fetch_add(-1) == 1) delete this; } 23 private: 24 std::atomic<size_t> refCounter; 25 }; 26 27 //////////////////////////////////////////////////////////////////////////////// 28 /// Reference to single object 29 //////////////////////////////////////////////////////////////////////////////// 30 31 template<typename Type> 32 class Ref 33 { 34 public: 35 Type* ptr; 36 37 //////////////////////////////////////////////////////////////////////////////// 38 /// Constructors, Assignment & Cast Operators 39 //////////////////////////////////////////////////////////////////////////////// 40 Ref()41 __forceinline Ref() : ptr(nullptr) {} Ref(NullTy)42 __forceinline Ref(NullTy) : ptr(nullptr) {} Ref(const Ref & input)43 __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); } Ref(Ref && input)44 __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; } 45 Ref(Type * const input)46 __forceinline Ref(Type* const input) : ptr(input) 47 { 48 if (ptr) 49 ptr->refInc(); 50 } 51 ~Ref()52 __forceinline ~Ref() 53 { 54 if (ptr) 55 ptr->refDec(); 56 } 57 58 __forceinline Ref& operator =(const Ref& input) 59 { 60 if (input.ptr) 61 input.ptr->refInc(); 62 if (ptr) 63 ptr->refDec(); 64 ptr = input.ptr; 65 return *this; 66 } 67 68 __forceinline Ref& operator =(Ref&& input) 69 { 70 if (ptr) 71 ptr->refDec(); 72 ptr = input.ptr; 73 input.ptr = nullptr; 74 return *this; 75 } 76 77 __forceinline Ref& operator =(Type* const input) 78 { 79 if (input) 80 input->refInc(); 81 if (ptr) 82 ptr->refDec(); 83 ptr = input; 84 return *this; 85 } 86 87 __forceinline Ref& operator =(NullTy) 88 { 89 if (ptr) 90 ptr->refDec(); 91 ptr = nullptr; 92 return *this; 93 } 94 95 __forceinline operator bool() const { return ptr != nullptr; } 96 97 __forceinline const Type& operator *() const { return *ptr; } 98 __forceinline Type& operator *() { return *ptr; } 99 __forceinline const Type* operator ->() const { return ptr; } 100 __forceinline Type* operator ->() { return ptr; } 101 102 template<typename TypeOut> cast()103 __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); } 104 template<typename TypeOut> cast()105 __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); } 106 107 template<typename TypeOut> dynamicCast()108 __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); } 109 template<typename TypeOut> dynamicCast()110 __forceinline const Ref<TypeOut> dynamicCast() const { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); } 111 }; 112 113 template<typename Type> __forceinline bool operator < (const Ref<Type>& a, const Ref<Type>& b) { return a.ptr < b.ptr; } 114 115 template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, NullTy ) { return a.ptr == nullptr; } 116 template<typename Type> __forceinline bool operator ==(NullTy , const Ref<Type>& b) { return nullptr == b.ptr; } 117 template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr == b.ptr; } 118 119 template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, NullTy ) { return a.ptr != nullptr; } 120 template<typename Type> __forceinline bool operator !=(NullTy , const Ref<Type>& b) { return nullptr != b.ptr; } 121 template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr != b.ptr; } 122 } 123