1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "atomic.h"
7
8namespace embree
9{
10 struct NullTy {
11 };
12
13 extern MAYBE_UNUSED NullTy null;
14
15 class RefCount
16 {
17 public:
18 RefCount(int val = 0) : refCounter(val) {}
19 virtual ~RefCount() {};
20
21 virtual RefCount* refInc() { refCounter.fetch_add(1); return this; }
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
41 __forceinline Ref() : ptr(nullptr) {}
42 __forceinline Ref(NullTy) : ptr(nullptr) {}
43 __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); }
44 __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; }
45
46 __forceinline Ref(Type* const input) : ptr(input)
47 {
48 if (ptr)
49 ptr->refInc();
50 }
51
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>
103 __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
104 template<typename TypeOut>
105 __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
106
107 template<typename TypeOut>
108 __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
109 template<typename TypeOut>
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