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 #ifndef JPH_TSAN_ENABLED
63 // Releasing a reference must use release semantics...
64 uint32 old_value = mRefCount.fetch_sub(1, memory_order_release);
65 if (old_value == 1)
66 {
67 // ... so that we can use acquire to ensure that we see any updates from other threads that released a ref before deleting the object
68 atomic_thread_fence(memory_order_acquire);
69 delete static_cast<const T *>(this);
70 }
71 #else
72 // But under TSAN, we cannot use atomic_thread_fence, so we use an acq_rel operation unconditionally instead
73 uint32 old_value = mRefCount.fetch_sub(1, memory_order_acq_rel);
74 if (old_value == 1)
75 delete static_cast<const T *>(this);
76 #endif
77 JPH_ASSERT(old_value != 0 && old_value != cEmbedded, "Too many calls to Release");
78 }
79
81 static int sInternalGetRefCountOffset() { return offsetof(T, mRefCount); }
82
83protected:
84 static constexpr uint32 cEmbedded = 0x0ebedded;
85
86 mutable atomic<uint32> mRefCount = 0;
87};
88
91{
92public:
94 virtual ~RefTargetVirtual() = default;
95
97 virtual void AddRef() = 0;
98
100 virtual void Release() = 0;
101};
102
108template <class T>
109class Ref
110{
111public:
113 inline Ref() : mPtr(nullptr) { }
114 inline Ref(T *inRHS) : mPtr(inRHS) { AddRef(); }
115 inline Ref(const Ref<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
116 inline Ref(Ref<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
117 inline ~Ref() { Release(); }
118
120 inline Ref<T> & operator = (T *inRHS) { if (mPtr != inRHS) { Release(); mPtr = inRHS; AddRef(); } return *this; }
121 inline Ref<T> & operator = (const Ref<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
122 inline Ref<T> & operator = (Ref<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
123
125 inline operator T *() const { return mPtr; }
126
128 inline T * operator -> () const { return mPtr; }
129 inline T & operator * () const { return *mPtr; }
130
132 inline bool operator == (const T * inRHS) const { return mPtr == inRHS; }
133 inline bool operator == (const Ref<T> &inRHS) const { return mPtr == inRHS.mPtr; }
134 inline bool operator != (const T * inRHS) const { return mPtr != inRHS; }
135 inline bool operator != (const Ref<T> &inRHS) const { return mPtr != inRHS.mPtr; }
136
138 inline T * GetPtr() const { return mPtr; }
139
142 {
143 return Hash<T *> { } (mPtr);
144 }
145
147 void ** InternalGetPointer() { return reinterpret_cast<void **>(&mPtr); }
148
149private:
150 template <class T2> friend class RefConst;
151
153 inline void AddRef() { if (mPtr != nullptr) mPtr->AddRef(); }
154 inline void Release() { if (mPtr != nullptr) mPtr->Release(); }
155
156 T * mPtr;
157};
158
164template <class T>
166{
167public:
169 inline RefConst() : mPtr(nullptr) { }
170 inline RefConst(const T * inRHS) : mPtr(inRHS) { AddRef(); }
171 inline RefConst(const RefConst<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
172 inline RefConst(RefConst<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
173 inline RefConst(const Ref<T> &inRHS) : mPtr(inRHS.mPtr) { AddRef(); }
174 inline RefConst(Ref<T> &&inRHS) noexcept : mPtr(inRHS.mPtr) { inRHS.mPtr = nullptr; }
175 inline ~RefConst() { Release(); }
176
178 inline RefConst<T> & operator = (const T * inRHS) { if (mPtr != inRHS) { Release(); mPtr = inRHS; AddRef(); } return *this; }
179 inline RefConst<T> & operator = (const RefConst<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
180 inline RefConst<T> & operator = (RefConst<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
181 inline RefConst<T> & operator = (const Ref<T> &inRHS) { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; AddRef(); } return *this; }
182 inline RefConst<T> & operator = (Ref<T> &&inRHS) noexcept { if (mPtr != inRHS.mPtr) { Release(); mPtr = inRHS.mPtr; inRHS.mPtr = nullptr; } return *this; }
183
185 inline operator const T * () const { return mPtr; }
186
188 inline const T * operator -> () const { return mPtr; }
189 inline const T & operator * () const { return *mPtr; }
190
192 inline bool operator == (const T * inRHS) const { return mPtr == inRHS; }
193 inline bool operator == (const RefConst<T> &inRHS) const { return mPtr == inRHS.mPtr; }
194 inline bool operator == (const Ref<T> &inRHS) const { return mPtr == inRHS.mPtr; }
195 inline bool operator != (const T * inRHS) const { return mPtr != inRHS; }
196 inline bool operator != (const RefConst<T> &inRHS) const { return mPtr != inRHS.mPtr; }
197 inline bool operator != (const Ref<T> &inRHS) const { return mPtr != inRHS.mPtr; }
198
200 inline const T * GetPtr() const { return mPtr; }
201
204 {
205 return Hash<const T *> { } (mPtr);
206 }
207
209 void ** InternalGetPointer() { return const_cast<void **>(reinterpret_cast<const void **>(&mPtr)); }
210
211private:
213 inline void AddRef() { if (mPtr != nullptr) mPtr->AddRef(); }
214 inline void Release() { if (mPtr != nullptr) mPtr->Release(); }
215
216 const T * mPtr;
217};
218
220
222JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
223
224namespace std
225{
227 template <class T>
228 struct hash<JPH::Ref<T>>
229 {
230 size_t operator () (const JPH::Ref<T> &inRHS) const
231 {
232 return size_t(inRHS.GetHash());
233 }
234 };
235
237 template <class T>
238 struct hash<JPH::RefConst<T>>
239 {
240 size_t operator () (const JPH::RefConst<T> &inRHS) const
241 {
242 return size_t(inRHS.GetHash());
243 }
244 };
245}
246
#define JPH_EXPORT
Definition Core.h:275
std::uint64_t uint64
Definition Core.h:504
#define JPH_NAMESPACE_END
Definition Core.h:425
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition Core.h:302
std::uint32_t uint32
Definition Core.h:503
#define JPH_NAMESPACE_BEGIN
Definition Core.h:419
#define JPH_IF_ENABLE_ASSERTS(...)
Definition IssueReporting.h:35
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
#define JPH_SUPPRESS_WARNING_POP
Definition ShaderCore.h:38
#define JPH_SUPPRESS_WARNING_PUSH
Definition ShaderCore.h:37
Definition Reference.h:166
const T * GetPtr() const
Get pointer.
Definition Reference.h:200
bool operator!=(const T *inRHS) const
Definition Reference.h:195
RefConst()
Constructor.
Definition Reference.h:169
~RefConst()
Definition Reference.h:175
RefConst(const T *inRHS)
Definition Reference.h:170
const T & operator*() const
Definition Reference.h:189
RefConst< T > & operator=(const T *inRHS)
Assignment operators.
Definition Reference.h:178
RefConst(const Ref< T > &inRHS)
Definition Reference.h:173
void ** InternalGetPointer()
INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
Definition Reference.h:209
const T * operator->() const
Access like a normal pointer.
Definition Reference.h:188
RefConst(RefConst< T > &&inRHS) noexcept
Definition Reference.h:172
uint64 GetHash() const
Get hash for this object.
Definition Reference.h:203
RefConst(const RefConst< T > &inRHS)
Definition Reference.h:171
bool operator==(const T *inRHS) const
Comparison.
Definition Reference.h:192
RefConst(Ref< T > &&inRHS) noexcept
Definition Reference.h:174
Definition Reference.h:110
Ref(const Ref< T > &inRHS)
Definition Reference.h:115
T * GetPtr() const
Get pointer.
Definition Reference.h:138
bool operator!=(const T *inRHS) const
Definition Reference.h:134
Ref()
Constructor.
Definition Reference.h:113
~Ref()
Definition Reference.h:117
T * operator->() const
Access like a normal pointer.
Definition Reference.h:128
void ** InternalGetPointer()
INTERNAL HELPER FUNCTION USED BY SERIALIZATION.
Definition Reference.h:147
Ref< T > & operator=(T *inRHS)
Assignment operators.
Definition Reference.h:120
Ref(Ref< T > &&inRHS) noexcept
Definition Reference.h:116
Ref(T *inRHS)
Definition Reference.h:114
uint64 GetHash() const
Get hash for this object.
Definition Reference.h:141
bool operator==(const T *inRHS) const
Comparison.
Definition Reference.h:132
T & operator*() const
Definition Reference.h:129
Definition Reference.h:35
void Release() const
Definition Reference.h:60
atomic< uint32 > mRefCount
Current reference count.
Definition Reference.h:86
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:81
~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:84
Pure virtual version of RefTarget.
Definition Reference.h:91
virtual ~RefTargetVirtual()=default
Virtual destructor.
virtual void Release()=0
Virtual release reference.
virtual void AddRef()=0
Virtual add reference.
Definition Array.h:699
Fallback hash function that calls T::GetHash()
Definition HashCombine.h:59