Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Reference.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <Jolt/Core/Atomics.h>
8
10
11// Forward declares
12template <class T> class Ref;
13template <class T> class RefConst;
14
33template <class T>
35{
36public:
38 inline RefTarget() = default;
39 inline RefTarget(const RefTarget &) { /* Do not copy refcount */ }
40 inline ~RefTarget() { JPH_IF_ENABLE_ASSERTS(uint32 value = mRefCount.load(memory_order_relaxed);) JPH_ASSERT(value == 0 || value == cEmbedded); }
41
45 inline void SetEmbedded() const { JPH_IF_ENABLE_ASSERTS(uint32 old = ) mRefCount.fetch_add(cEmbedded, memory_order_relaxed); JPH_ASSERT(old < cEmbedded); }
46
48 inline RefTarget & operator = (const RefTarget &) { /* Don't copy refcount */ return *this; }
49
51 uint32 GetRefCount() const { return mRefCount.load(memory_order_relaxed); }
52
54 inline void AddRef() const
55 {
56 // Adding a reference can use relaxed memory ordering
57 mRefCount.fetch_add(1, memory_order_relaxed);
58 }
59
60 inline void Release() const
61 {
62 // Releasing a reference must use release semantics...
63 if (mRefCount.fetch_sub(1, memory_order_release) == 1)
64 {
65 // ... so that we can use aquire to ensure that we see any updates from other threads that released a ref before deleting the object
66 atomic_thread_fence(memory_order_acquire);
67 delete static_cast<const T *>(this);
68 }
69 }
70
72 static int sInternalGetRefCountOffset() { return offsetof(T, mRefCount); }
73
74protected:
75 static constexpr uint32 cEmbedded = 0x0ebedded;
76
77 mutable atomic<uint32> mRefCount = 0;
78};
79
82{
83public:
85 virtual ~RefTargetVirtual() = default;
86
88 virtual void AddRef() = 0;
89
91 virtual void Release() = 0;
92};
93
99template <class T>
100class Ref
101{
102public:
104 inline Ref() : mPtr(nullptr) { }
105 inline Ref(T *inRHS) : mPtr(inRHS) { AddRef(); }
106 inline Ref(const Ref<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
107 inline Ref(Ref<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
108 inline ~Ref() { Release(); }
109
111 inline Ref<T> & operator = (T *inRHS) { if (mPtr != inRHS) { Release(); mPtr = inRHS; AddRef(); } return *this; }
112 inline Ref<T> & operator = (const Ref<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
113 inline Ref<T> & operator = (Ref<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
114
116 inline operator T * const () const { return mPtr; }
117 inline operator T *() { return mPtr; }
118
120 inline T * const operator -> () const { return mPtr; }
121 inline T * operator -> () { return mPtr; }
122 inline T & operator * () const { return *mPtr; }
123
125 inline bool operator == (const T * inRHS) const { return mPtr == inRHS; }
126 inline bool operator == (const Ref<T> &inRHS) const { return mPtr == inRHS.mPtr; }
127 inline bool operator != (const T * inRHS) const { return mPtr != inRHS; }
128 inline bool operator != (const Ref<T> &inRHS) const { return mPtr != inRHS.mPtr; }
129
131 inline T * GetPtr() const { return mPtr; }
132 inline T * GetPtr() { return mPtr; }
133
135 void ** InternalGetPointer() { return reinterpret_cast<void **>(&mPtr); }
136
137private:
138 template <class T2> friend class RefConst;
139
141 inline void AddRef() { if (mPtr != nullptr) mPtr->AddRef(); }
142 inline void Release() { if (mPtr != nullptr) mPtr->Release(); }
143
144 T * mPtr;
145};
146
152template <class T>
154{
155public:
157 inline RefConst() : mPtr(nullptr) { }
158 inline RefConst(const T * inRHS) : mPtr(inRHS) { AddRef(); }
159 inline RefConst(const RefConst<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
160 inline RefConst(RefConst<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
161 inline RefConst(const Ref<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
162 inline RefConst(Ref<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
163 inline ~RefConst() { Release(); }
164
166 inline RefConst<T> & operator = (const T * inRHS) { if (mPtr != inRHS) { Release(); mPtr = inRHS; AddRef(); } return *this; }
167 inline RefConst<T> & operator = (const RefConst<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
168 inline RefConst<T> & operator = (RefConst<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
169 inline RefConst<T> & operator = (const Ref<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
170 inline RefConst<T> & operator = (Ref<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
171
173 inline operator const T * () const { return mPtr; }
174
176 inline const T * operator -> () const { return mPtr; }
177 inline const T & operator * () const { return *mPtr; }
178
180 inline bool operator == (const T * inRHS) const { return mPtr == inRHS; }
181 inline bool operator == (const RefConst<T> &inRHS) const { return mPtr == inRHS.mPtr; }
182 inline bool operator == (const Ref<T> &inRHS) const { return mPtr == inRHS.mPtr; }
183 inline bool operator != (const T * inRHS) const { return mPtr != inRHS; }
184 inline bool operator != (const RefConst<T> &inRHS) const { return mPtr != inRHS.mPtr; }
185 inline bool operator != (const Ref<T> &inRHS) const { return mPtr != inRHS.mPtr; }
186
188 inline const T * GetPtr() const { return mPtr; }
189
191 void ** InternalGetPointer() { return const_cast<void **>(reinterpret_cast<const void **>(&mPtr)); }
192
193private:
195 inline void AddRef() { if (mPtr != nullptr) mPtr->AddRef(); }
196 inline void Release() { if (mPtr != nullptr) mPtr->Release(); }
197
198 const T * mPtr;
199};
200
202
203JPH_SUPPRESS_WARNING_PUSH
204JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
205
206namespace std
207{
209 template <class T>
210 struct hash<JPH::Ref<T>>
211 {
212 size_t operator () (const JPH::Ref<T> &inRHS) const
213 {
214 return hash<T *> { }(inRHS.GetPtr());
215 }
216 };
217
219 template <class T>
220 struct hash<JPH::RefConst<T>>
221 {
222 size_t operator () (const JPH::RefConst<T> &inRHS) const
223 {
224 return hash<const T *> { }(inRHS.GetPtr());
225 }
226 };
227}
228
229JPH_SUPPRESS_WARNING_POP
uint32_t uint32
Definition: Core.h:312
#define JPH_NAMESPACE_END
Definition: Core.h:240
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition: Core.h:133
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:234
#define JPH_IF_ENABLE_ASSERTS(...)
Definition: IssueReporting.h:35
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
Definition: Reference.h:154
const T * GetPtr() const
Get pointer.
Definition: Reference.h:188
bool operator!=(const T *inRHS) const
Definition: Reference.h:183
RefConst()
Constructor.
Definition: Reference.h:157
~RefConst()
Definition: Reference.h:163
RefConst(const T *inRHS)
Definition: Reference.h:158
const T & operator*() const
Definition: Reference.h:177
RefConst< T > & operator=(const T *inRHS)
Assignment operators.
Definition: Reference.h:166
RefConst(const Ref< T > &inRHS)
Definition: Reference.h:161
void ** InternalGetPointer()
INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
Definition: Reference.h:191
const T * operator->() const
Access like a normal pointer.
Definition: Reference.h:176
RefConst(RefConst< T > &&inRHS) noexcept
Definition: Reference.h:160
RefConst(const RefConst< T > &inRHS)
Definition: Reference.h:159
bool operator==(const T *inRHS) const
Comparison.
Definition: Reference.h:180
RefConst(Ref< T > &&inRHS) noexcept
Definition: Reference.h:162
Definition: Reference.h:101
Ref(const Ref< T > &inRHS)
Definition: Reference.h:106
T * GetPtr() const
Get pointer.
Definition: Reference.h:131
bool operator!=(const T *inRHS) const
Definition: Reference.h:127
Ref()
Constructor.
Definition: Reference.h:104
~Ref()
Definition: Reference.h:108
void ** InternalGetPointer()
INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
Definition: Reference.h:135
Ref< T > & operator=(T *inRHS)
Assignment operators.
Definition: Reference.h:111
Ref(Ref< T > &&inRHS) noexcept
Definition: Reference.h:107
Ref(T *inRHS)
Definition: Reference.h:105
bool operator==(const T *inRHS) const
Comparison.
Definition: Reference.h:125
T *const operator->() const
Access like a normal pointer.
Definition: Reference.h:120
T & operator*() const
Definition: Reference.h:122
T * GetPtr()
Definition: Reference.h:132
Definition: Reference.h:35
void Release() const
Definition: Reference.h:60
atomic< uint32 > mRefCount
Current reference count.
Definition: Reference.h:77
RefTarget & operator=(const RefTarget &)
Assignment operator.
Definition: Reference.h:48
void SetEmbedded() const
Definition: Reference.h:45
RefTarget()=default
Constructor.
RefTarget(const RefTarget &)
Definition: Reference.h:39
static int sInternalGetRefCountOffset()
INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
Definition: Reference.h:72
~RefTarget()
assert no one is referencing us
Definition: Reference.h:40
uint32 GetRefCount() const
Get current refcount of this object.
Definition: Reference.h:51
void AddRef() const
Add or release a reference to this object.
Definition: Reference.h:54
static constexpr uint32 cEmbedded
A large value that gets added to the refcount to mark the object as embedded.
Definition: Reference.h:75
Pure virtual version of RefTarget.
Definition: Reference.h:82
virtual ~RefTargetVirtual()=default
Virtual destructor.
virtual void Release()=0
Virtual release reference.
virtual void AddRef()=0
Virtual add reference.
Definition: Reference.h:207