Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
RefCounting.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
6#include "HAL/PlatformAtomics.h"
7#include "HAL/PreprocessorHelpers.h"
8#include "HAL/ThreadSafeCounter.h"
9#include "Misc/AssertionMacros.h"
10#include "Misc/Build.h"
11#include "Serialization/Archive.h"
12#include "Serialization/MemoryLayout.h"
13#include "Templates/TypeHash.h"
14
15/** A virtual interface for ref counted objects to implement. */
17{
18public:
19 virtual ~IRefCountedObject() { }
20 virtual uint32 AddRef() const = 0;
21 virtual uint32 Release() const = 0;
22 virtual uint32 GetRefCount() const = 0;
23};
24
25/**
26 * Base class implementing thread-safe reference counting.
27 */
29{
30public:
31 FRefCountBase() = default;
32 virtual ~FRefCountBase() = default;
33
34 FRefCountBase(const FRefCountBase& Rhs) = delete;
35 FRefCountBase& operator=(const FRefCountBase& Rhs) = delete;
36
37 inline uint32 AddRef() const
38 {
39 return uint32(FPlatformAtomics::InterlockedIncrement(&NumRefs));
40 }
41
42 inline uint32 Release() const
43 {
45 if (NumRefs == 0)
46 {
47 CheckRefCount();
48 }
49#endif
50
51 const int32 Refs = FPlatformAtomics::InterlockedDecrement(&NumRefs);
52 if (Refs == 0)
53 {
54 delete this;
55 }
56
57 return uint32(Refs);
58 }
59
60 uint32 GetRefCount() const
61 {
62 return uint32(NumRefs);
63 }
64
65private:
66 mutable int32 NumRefs = 0;
67
68 void CheckRefCount() const;
69};
70
71/**
72 * The base class of reference counted objects.
73 *
74 * This class should not be used for new code as it does not use atomic operations to update
75 * the reference count.
76 *
77 */
79{
80public:
82 virtual ~FRefCountedObject() { check(!NumRefs); }
85 uint32 AddRef() const
86 {
87 return uint32(++NumRefs);
88 }
89 uint32 Release() const
90 {
91 uint32 Refs = uint32(--NumRefs);
92 if(Refs == 0)
93 {
94 delete this;
95 }
96 return Refs;
97 }
98 uint32 GetRefCount() const
99 {
100 return uint32(NumRefs);
101 }
102private:
103 mutable int32 NumRefs;
104};
105
106/**
107 * Like FRefCountedObject, but internal ref count is thread safe
108 */
110{
111public:
113 virtual ~FThreadSafeRefCountedObject() { check(NumRefs.GetValue() == 0); }
116 uint32 AddRef() const
117 {
118 return uint32(NumRefs.Increment());
119 }
120 uint32 Release() const
121 {
122 uint32 Refs = uint32(NumRefs.Decrement());
123 if (Refs == 0)
124 {
125 delete this;
126 }
127 return Refs;
128 }
129 uint32 GetRefCount() const
130 {
131 return uint32(NumRefs.GetValue());
132 }
133private:
135};
136
137
138
139/**
140 * A smart pointer to an object which implements AddRef/Release.
141 */
142template<typename ReferencedType>
144{
145 typedef ReferencedType* ReferenceType;
146
147public:
148
150 Reference(nullptr)
151 { }
152
153 TRefCountPtr(ReferencedType* InReference,bool bAddRef = true)
154 {
156 if(Reference && bAddRef)
157 {
158 Reference->AddRef();
159 }
160 }
161
163 {
165 if(Reference)
166 {
167 Reference->AddRef();
168 }
169 }
170
171 template<typename CopyReferencedType>
172 explicit TRefCountPtr(const TRefCountPtr<CopyReferencedType>& Copy)
173 {
174 Reference = static_cast<ReferencedType*>(Copy.GetReference());
175 if (Reference)
176 {
177 Reference->AddRef();
178 }
179 }
180
182 {
184 Move.Reference = nullptr;
185 }
186
187 template<typename MoveReferencedType>
188 explicit TRefCountPtr(TRefCountPtr<MoveReferencedType>&& Move)
189 {
190 Reference = static_cast<ReferencedType*>(Move.GetReference());
191 Move.Reference = nullptr;
192 }
193
195 {
196 if(Reference)
197 {
199 }
200 }
201
202 TRefCountPtr& operator=(ReferencedType* InReference)
203 {
204 if (Reference != InReference)
205 {
206 // Call AddRef before Release, in case the new reference is the same as the old reference.
209 if (Reference)
210 {
211 Reference->AddRef();
212 }
213 if (OldReference)
214 {
216 }
217 }
218 return *this;
219 }
220
222 {
223 return *this = InPtr.Reference;
224 }
225
226 template<typename CopyReferencedType>
227 FORCEINLINE TRefCountPtr& operator=(const TRefCountPtr<CopyReferencedType>& InPtr)
228 {
229 return *this = InPtr.GetReference();
230 }
231
233 {
234 if (this != &InPtr)
235 {
238 InPtr.Reference = nullptr;
239 if(OldReference)
240 {
242 }
243 }
244 return *this;
245 }
246
247 template<typename MoveReferencedType>
248 TRefCountPtr& operator=(TRefCountPtr<MoveReferencedType>&& InPtr)
249 {
250 // InPtr is a different type (or we would have called the other operator), so we need not test &InPtr != this
253 InPtr.Reference = nullptr;
254 if (OldReference)
255 {
257 }
258 return *this;
259 }
260
261 FORCEINLINE ReferencedType* operator->() const
262 {
263 return Reference;
264 }
265
267 {
268 return Reference;
269 }
270
271 FORCEINLINE ReferencedType** GetInitReference()
272 {
273 *this = nullptr;
274 return &Reference;
275 }
276
277 FORCEINLINE ReferencedType* GetReference() const
278 {
279 return Reference;
280 }
281
282 FORCEINLINE friend bool IsValidRef(const TRefCountPtr& InReference)
283 {
284 return InReference.Reference != nullptr;
285 }
286
287 FORCEINLINE bool IsValid() const
288 {
289 return Reference != nullptr;
290 }
291
293 {
294 *this = nullptr;
295 }
296
297 uint32 GetRefCount()
298 {
299 uint32 Result = 0;
300 if (Reference)
301 {
303 check(Result > 0); // you should never have a zero ref count if there is a live ref counted pointer (*this is live)
304 }
305 return Result;
306 }
307
308 FORCEINLINE void Swap(TRefCountPtr& InPtr) // this does not change the reference count, and so is faster
309 {
313 }
314
316 {
318 Ar << PtrReference;
319 if(Ar.IsLoading())
320 {
321 *this = PtrReference;
322 }
323 }
324
325private:
326
327 ReferencedType* Reference;
328
329 template <typename OtherType>
330 friend class TRefCountPtr;
331
332public:
333 FORCEINLINE bool operator==(const TRefCountPtr& B) const
334 {
335 return GetReference() == B.GetReference();
336 }
337
338 FORCEINLINE bool operator==(ReferencedType* B) const
339 {
340 return GetReference() == B;
341 }
342};
343
344ALIAS_TEMPLATE_TYPE_LAYOUT(template<typename T>, TRefCountPtr<T>, void*);
345
347template<typename ReferencedType>
348FORCEINLINE bool operator==(ReferencedType* A, const TRefCountPtr<ReferencedType>& B)
349{
350 return A == B.GetReference();
351}
352#endif
353
354template<typename ReferencedType>
355FORCEINLINE uint32 GetTypeHash(const TRefCountPtr<ReferencedType>& InPtr)
356{
357 return GetTypeHash(InPtr.GetReference());
358}
359
360
361template<typename ReferencedType>
362FArchive& operator<<(FArchive& Ar,TRefCountPtr<ReferencedType>& Ptr)
363{
364 Ptr.Serialize(Ar);
365 return Ar;
366}
#define check(expr)
#define DO_GUARD_SLOW
Definition Build.h:308
#define ALIAS_TEMPLATE_TYPE_LAYOUT(TemplatePrefix, T, Alias)
#define FORCEINLINE
Definition Platform.h:644
#define PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
Definition Platform.h:250
FORCEINLINE uint32 GetTypeHash(const TRefCountPtr< ReferencedType > &InPtr)
FORCEINLINE bool operator==(ReferencedType *A, const TRefCountPtr< ReferencedType > &B)
FRefCountBase()=default
uint32 GetRefCount() const
Definition RefCounting.h:60
uint32 AddRef() const
Definition RefCounting.h:37
FRefCountBase(const FRefCountBase &Rhs)=delete
void CheckRefCount() const
virtual ~FRefCountBase()=default
uint32 Release() const
Definition RefCounting.h:42
FRefCountBase & operator=(const FRefCountBase &Rhs)=delete
virtual ~FRefCountedObject()
Definition RefCounting.h:82
FRefCountedObject & operator=(const FRefCountedObject &Rhs)=delete
uint32 AddRef() const
Definition RefCounting.h:85
uint32 Release() const
Definition RefCounting.h:89
FRefCountedObject(const FRefCountedObject &Rhs)=delete
uint32 GetRefCount() const
Definition RefCounting.h:98
FThreadSafeCounter(int32 Value)
FThreadSafeCounter NumRefs
FThreadSafeRefCountedObject(const FThreadSafeRefCountedObject &Rhs)=delete
FThreadSafeRefCountedObject & operator=(const FThreadSafeRefCountedObject &Rhs)=delete
virtual uint32 AddRef() const =0
virtual uint32 GetRefCount() const =0
virtual ~IRefCountedObject()
Definition RefCounting.h:19
virtual uint32 Release() const =0
TRefCountPtr(TRefCountPtr< MoveReferencedType > &&Move)
ReferencedType * ReferenceType
uint32 GetRefCount()
ReferencedType * Reference
void Serialize(FArchive &Ar)
TRefCountPtr(const TRefCountPtr &Copy)
TRefCountPtr & operator=(ReferencedType *InReference)
FORCEINLINE friend bool IsValidRef(const TRefCountPtr &InReference)
FORCEINLINE operator ReferenceType() const
FORCEINLINE void SafeRelease()
TRefCountPtr(const TRefCountPtr< CopyReferencedType > &Copy)
TRefCountPtr & operator=(TRefCountPtr< MoveReferencedType > &&InPtr)
TRefCountPtr & operator=(TRefCountPtr &&InPtr)
FORCEINLINE TRefCountPtr & operator=(const TRefCountPtr< CopyReferencedType > &InPtr)
FORCEINLINE bool operator==(ReferencedType *B) const
FORCEINLINE TRefCountPtr()
FORCEINLINE TRefCountPtr & operator=(const TRefCountPtr &InPtr)
FORCEINLINE bool IsValid() const
FORCEINLINE ReferencedType ** GetInitReference()
FORCEINLINE TRefCountPtr(TRefCountPtr &&Move)
FORCEINLINE bool operator==(const TRefCountPtr &B) const
TRefCountPtr(ReferencedType *InReference, bool bAddRef=true)
FORCEINLINE ReferencedType * GetReference() const
FORCEINLINE void Swap(TRefCountPtr &InPtr)
FORCEINLINE ReferencedType * operator->() const