UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
RefCountVector.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3// Port of geometry3cpp FRefCountVector
4
5#pragma once
6
7#include "CoreMinimal.h"
9#include "Util/IteratorUtil.h"
10
11namespace UE
12{
13namespace Geometry
14{
15
25{
26public:
27 static constexpr unsigned short INVALID_REF_COUNT = MAX_uint16;
28
29 FRefCountVector() = default;
32 RefCounts(MoveTemp(From.RefCounts)), FreeIndices(MoveTemp(From.FreeIndices)), UsedCount(From.UsedCount)
33 {
34 From.UsedCount = 0;
35 }
38 {
39 RefCounts = MoveTemp(From.RefCounts);
40 FreeIndices = MoveTemp(From.FreeIndices);
41 UsedCount = From.UsedCount;
42 From.UsedCount = 0;
43 return *this;
44 }
45
46 bool IsEmpty() const
47 {
48 return UsedCount == 0;
49 }
50
51 size_t GetCount() const
52 {
53 return UsedCount;
54 }
55
56 size_t GetMaxIndex() const
57 {
58 return RefCounts.GetLength();
59 }
60
61 bool IsDense() const
62 {
63 return FreeIndices.GetLength() == 0;
64 }
65
66 bool IsValid(int Index) const
67 {
68 return (Index >= 0 && Index < (int)RefCounts.GetLength() && IsValidUnsafe(Index));
69 }
70
71 bool IsValidUnsafe(int Index) const
72 {
73 return RefCounts[Index] > 0 && RefCounts[Index] < INVALID_REF_COUNT;
74 }
75
76 int GetRefCount(int Index) const
77 {
78 int n = RefCounts[Index];
79 return (n == INVALID_REF_COUNT) ? 0 : n;
80 }
81
82 int GetRawRefCount(int Index) const
83 {
84 return RefCounts[Index];
85 }
86
87 // Append all ref counts from another RefCountVector, offsetting FreeIndices to refer to their corresponded new array positions
88 // Note this does not try to 'fill in' original free indices, by design -- all existing IDs remain untouched, and all new IDs are simply offsets of the Other's IDs
90 {
91 size_t OrigNum = RefCounts.Num();
92 size_t OrigFree = FreeIndices.Num();
93 RefCounts.Add(Other.RefCounts);
94 FreeIndices.Add(Other.FreeIndices);
95 for (size_t Idx = OrigFree, N = FreeIndices.Num(); Idx < N; ++Idx)
96 {
97 FreeIndices[Idx] += OrigNum;
98 }
99 UsedCount += Other.UsedCount;
100 }
101
103 {
104 UsedCount++;
105 if (FreeIndices.IsEmpty())
106 {
107 // TODO: do we need this branch anymore?
108 RefCounts.Add(1);
109 return (int)RefCounts.GetLength() - 1;
110 }
111 else
112 {
113 int iFree = INDEX_NONE;
114 while (iFree == INDEX_NONE && FreeIndices.IsEmpty() == false)
115 {
116 iFree = FreeIndices.Back();
117 FreeIndices.PopBack();
118 }
119 if (iFree != INDEX_NONE)
120 {
121 RefCounts[iFree] = 1;
122 return iFree;
123 }
124 else
125 {
126 RefCounts.Add(1);
127 return (int)RefCounts.GetLength() - 1;
128 }
129 }
130 }
131
132 int Increment(int Index, unsigned short IncrementCount = 1)
133 {
134 checkSlow(RefCounts[Index] != INVALID_REF_COUNT);
135 RefCounts[Index] += IncrementCount;
136 return RefCounts[Index];
137 }
138
139 void Decrement(int Index, unsigned short DecrementCount = 1)
140 {
141 checkSlow(RefCounts[Index] != INVALID_REF_COUNT && RefCounts[Index] >= DecrementCount);
142 RefCounts[Index] -= DecrementCount;
143 if (RefCounts[Index] == 0)
144 {
145 FreeIndices.Add(Index);
146 RefCounts[Index] = INVALID_REF_COUNT;
147 UsedCount--;
148 }
149 }
150
159 {
160 if (Index >= (int)RefCounts.GetLength())
161 {
162 int j = (int)RefCounts.GetLength();
163 while (j < Index)
164 {
165 unsigned short InvalidCount = INVALID_REF_COUNT; // required on older clang because a constexpr can't be passed by ref
166 RefCounts.Add(InvalidCount);
167 FreeIndices.Add(j);
168 ++j;
169 }
170 RefCounts.Add(1);
171 UsedCount++;
172 return true;
173 }
174 else
175 {
176 if (IsValidUnsafe(Index))
177 {
178 return false;
179 }
180 int N = (int)FreeIndices.GetLength();
181 for (int i = 0; i < N; ++i)
182 {
183 if (FreeIndices[i] == Index)
184 {
185 FreeIndices[i] = FreeIndices.Back();
186 FreeIndices.PopBack();
187 RefCounts[Index] = 1;
188 UsedCount++;
189 return true;
190 }
191 }
192 return false;
193 }
194 }
195
201 {
202 if (Index >= (int)RefCounts.GetLength())
203 {
204 int j = (int)RefCounts.GetLength();
205 while (j < Index)
206 {
207 unsigned short InvalidCount = INVALID_REF_COUNT; // required on older clang because a constexpr can't be passed by ref
208 RefCounts.Add(InvalidCount);
209 ++j;
210 }
211 RefCounts.Add(1);
212 UsedCount++;
213 return true;
214
215 }
216 else
217 {
218 if (IsValidUnsafe(Index))
219 {
220 return false;
221 }
222 RefCounts[Index] = 1;
223 UsedCount++;
224 return true;
225 }
226 }
227
229 {
230 return RefCounts;
231 }
232
237 {
238 return RefCounts;
239 }
240
244 void SetRefCountUnsafe(int Index, unsigned short ToCount)
245 {
246 RefCounts[Index] = ToCount;
247 }
248
249 // todo:
250 // remove
251 // clear
252
265 template <typename IterateFunc, typename AllocateRefCountFunc, typename IncrementRefCountFunc>
266 void Rebuild(unsigned int Num, IterateFunc&& Iterate, AllocateRefCountFunc&& AllocateRefCount, IncrementRefCountFunc&& IncrementRefCount)
267 {
268 // Initialize ref counts to the given number of elements.
269 RefCounts.Resize(Num);
270 RefCounts.Fill(INVALID_REF_COUNT);
271 UsedCount = 0;
272
273 // Lambda for updating ref count for a given index. This is passed to the external iterate function.
274 const auto UpdateRefCount = [this, &AllocateRefCount, &IncrementRefCount](int32 Index)
275 {
276 unsigned short& RefCount = RefCounts[Index];
277 if (RefCount == INVALID_REF_COUNT)
278 {
279 // Increase used counter and call external function to initialize value.
280 ++UsedCount;
282 }
283 else
284 {
285 // Call external function to initialize value.
286 Forward<IncrementRefCountFunc>(IncrementRefCount)(RefCount);
287 }
288 };
289
290 // Call external function that iterates over all external pieces of data, which will in turn call the lambda to update ref counts.
292
293 // Add unused elements to free list.
294 const unsigned int FreeIndicesNum = Num - UsedCount;
295 FreeIndices.SetNum(FreeIndicesNum);
296 unsigned int FreeIndicesIndex = 0;
297 for (unsigned int Index = 0; (Index < Num) & (FreeIndicesIndex < FreeIndicesNum); ++Index)
298 {
299 if (RefCounts[Index] == INVALID_REF_COUNT)
300 {
301 FreeIndices[FreeIndicesIndex++] = Index;
302 }
303 }
304 }
305
307 {
308 FreeIndices.Clear();
309 UsedCount = 0;
310
311 int N = (int)RefCounts.GetLength();
312 for (int i = 0; i < N; ++i)
313 {
314 if (IsValidUnsafe(i))
315 {
316 UsedCount++;
317 }
318 else
319 {
320 FreeIndices.Add(i);
321 }
322 }
323 }
324
325 void Trim(int maxIndex)
326 {
327 FreeIndices.Clear();
328 RefCounts.Resize(maxIndex);
329 UsedCount = maxIndex;
330 }
331
332 void Clear()
333 {
334 FreeIndices.Clear();
335 RefCounts.Clear();
336 UsedCount = 0;
337 }
338
339 // initialize and set all refcounts to given value
341 {
342 FreeIndices.Clear();
343 RefCounts.Clear();
344 RefCounts.Resize(Size, RefCountValue);
345 UsedCount = Size;
346 }
347 //
348 // Iterators
349 //
350
355 {
356 public:
358 {
359 Vector = nullptr;
360 Index = 0;
361 LastIndex = 0;
362 }
363
364 inline bool operator==(const BaseIterator& Other) const
365 {
366 return Index == Other.Index;
367 }
368 inline bool operator!=(const BaseIterator& Other) const
369 {
370 return Index != Other.Index;
371 }
372
373 protected:
374 inline void goto_next()
375 {
376 Index++;
378 {
379 Index++;
380 }
381 }
382
384 {
386 Index = IndexIn;
388 if (Index != LastIndex && Vector->IsValidUnsafe(Index) == false)
389 {
390 goto_next(); // initialize
391 }
392 }
394 int Index;
396 friend class FRefCountVector;
397 };
398
399 /*
400 * iterator over valid indices (ie non-zero refcount)
401 */
403 {
404 public:
406
407 inline int operator*() const
408 {
409 return this->Index;
410 }
411
412 inline IndexIterator & operator++() // prefix
413 {
414 this->goto_next();
415 return *this;
416 }
417 inline IndexIterator operator++(int) // postfix
418 {
419 IndexIterator copy(*this);
420 this->goto_next();
421 return copy;
422 }
423
424 protected:
427 friend class FRefCountVector;
428 };
429
431 {
432 return IndexIterator(this, (int)0, (int)RefCounts.GetLength());
433 }
434
436 {
437 return IndexIterator(this, (int)RefCounts.GetLength(), (int)RefCounts.GetLength());
438 }
439
453
459 {
460 return IndexEnumerable(this);
461 }
462
463
464 /*
465 * enumerable object that maps indices output by Index_iteration to a second type
466 */
467 template<typename ToType>
490
491
496 template<typename ToType>
497 inline MappedEnumerable<ToType> MappedIndices(TFunction<ToType(int)> MapFunc) const
498 {
499 return MappedEnumerable<ToType>(Indices(), MapFunc);
500 }
501
502 /*
503 * iteration object that maps indices output by Index_iteration to a second type
504 */
526
527 inline FilteredEnumerable FilteredIndices(TFunction<bool(int)> FilterFunc) const
528 {
529 return FilteredEnumerable(Indices(), FilterFunc);
530 }
531
532 FString UsageStats() const
533 {
534 return FString::Printf(TEXT("RefCountSize %zu FreeSize %zu FreeMem %zukb"),
535 RefCounts.GetLength(), FreeIndices.GetLength(), (FreeIndices.GetByteCount() / 1024));
536 }
537
539 {
540 return RefCounts.GetByteCount() + FreeIndices.GetByteCount();
541 }
542
551 {
552 Vec.Serialize(Ar, false, false);
553 return Ar;
554 }
555
562 void Serialize(FArchive& Ar, bool bCompactData, bool bUseCompression)
563 {
565 if (Ar.IsLoading() && Ar.CustomVer(FUE5MainStreamObjectVersion::GUID) < FUE5MainStreamObjectVersion::DynamicMeshCompactedSerialization)
566 {
567 Ar << RefCounts;
568 Ar << FreeIndices;
569 Ar << UsedCount;
570 }
571 else
572 {
573 // Serialize options.
574 Ar << bCompactData;
575 Ar << bUseCompression;
576
577 // Serialize number of used ref counts. While this is redundant to the contents of the ref count vector, it allows us to accelerate restoring the
578 // free indices and therefore it is worth the very minor storage overhead.
579 Ar << UsedCount;
580
581 // Serialize ref counts.
582 if (bUseCompression)
583 {
584 RefCounts.Serialize<true, true>(Ar);
585 }
586 else
587 {
588 RefCounts.Serialize<true, false>(Ar);
589 }
590
591 if (UsedCount == RefCounts.Num())
592 {
593 // If all ref counts are used then we can ignore the free indices entirely during save, and just clear them during load.
594
595 if (Ar.IsLoading() && !FreeIndices.IsEmpty())
596 {
597 FreeIndices.Clear();
598 }
599 }
600 else
601 {
602 // Compact the data by omitting the free indices entirely during save and recompute them during load.
603 // Considering the significant time overhead for compression, we compact if either bCompactData or bUseCompression is enabled.
604 if (bCompactData || bUseCompression)
605 {
606 if (Ar.IsLoading())
607 {
608 // Rebuild the free indices from the invalid ref count values.
609 const size_t NumFree = RefCounts.Num() - UsedCount;
610 FreeIndices.Resize(NumFree);
611 size_t Index = 0;
612 for (size_t i = 0, Num = RefCounts.Num(); (i < Num) & (Index < NumFree); ++i)
613 {
614 if (RefCounts[i] == INVALID_REF_COUNT)
615 {
616 FreeIndices[Index++] = i;
617 }
618 }
619 ensure(Index == NumFree);
620 }
621 }
622 else
623 {
624 FreeIndices.Serialize<true, false>(Ar);
625 }
626 }
627 }
628 }
629
630 friend bool operator==(const FRefCountVector& Lhs, const FRefCountVector& Rhs)
631 {
632 if (Lhs.GetCount() != Rhs.GetCount())
633 {
634 return false;
635 }
636
637 const size_t Num = FMath::Max(Lhs.GetMaxIndex(), Rhs.GetMaxIndex());
638 for (size_t Idx = 0; Idx < Num; ++Idx)
639 {
640 const bool LhsIsValid = Lhs.IsValid(Idx);
641 if (LhsIsValid != Rhs.IsValid(Idx))
642 {
643 return false;
644 }
645 if (LhsIsValid && Lhs.GetRefCount(Idx) != Rhs.GetRefCount(Idx))
646 {
647 return false;
648 }
649 }
650
651 return true;
652 }
653
654 friend bool operator!=(const FRefCountVector& Lhs, const FRefCountVector& Rhs)
655 {
656 return !(Lhs == Rhs);
657 }
658
659private:
661 TDynamicVector<int> FreeIndices{};
662 int UsedCount{0};
663
664
665};
666
667
668} // end namespace UE::Geometry
669} // end namespace UE
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define ensure( InExpression)
Definition AssertionMacros.h:464
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ Num
Definition MetalRHIPrivate.h:234
const bool
Definition NetworkReplayStreaming.h:178
#define MAX_uint16
Definition NumericLimits.h:20
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Size
Definition VulkanMemory.cpp:4034
uint16_t uint16
Definition binka_ue_file_header.h:7
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
virtual CORE_API void UsingCustomVersion(const struct FGuid &Guid)
Definition Archive.cpp:590
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
CORE_API int32 CustomVer(const struct FGuid &Key) const
Definition Archive.cpp:602
Definition AndroidPlatformMisc.h:14
Definition RefCountVector.h:355
bool operator==(const BaseIterator &Other) const
Definition RefCountVector.h:364
int LastIndex
Definition RefCountVector.h:395
BaseIterator(const FRefCountVector *VectorIn, int IndexIn, int LastIn)
Definition RefCountVector.h:383
void goto_next()
Definition RefCountVector.h:374
const FRefCountVector * Vector
Definition RefCountVector.h:393
int Index
Definition RefCountVector.h:394
bool operator!=(const BaseIterator &Other) const
Definition RefCountVector.h:368
BaseIterator()
Definition RefCountVector.h:357
FilteredEnumerable(const IndexEnumerable &enumerable, TFunction< bool(int)> FilterFuncIn)
Definition RefCountVector.h:510
TFunction< bool(int)> FilterFunc
Definition RefCountVector.h:508
IndexEnumerable enumerable
Definition RefCountVector.h:509
FilteredIterator< int, IndexIterator > end()
Definition RefCountVector.h:521
FilteredIterator< int, IndexIterator > begin()
Definition RefCountVector.h:516
Definition RefCountVector.h:445
FRefCountVector::IndexIterator begin() const
Definition RefCountVector.h:450
IndexEnumerable()
Definition RefCountVector.h:448
const FRefCountVector * Vector
Definition RefCountVector.h:447
IndexEnumerable(const FRefCountVector *VectorIn)
Definition RefCountVector.h:449
FRefCountVector::IndexIterator end() const
Definition RefCountVector.h:451
Definition RefCountVector.h:403
IndexIterator(const FRefCountVector *VectorIn, int Index, int Last)
Definition RefCountVector.h:425
IndexIterator()
Definition RefCountVector.h:405
int operator*() const
Definition RefCountVector.h:407
IndexIterator & operator++()
Definition RefCountVector.h:412
IndexIterator operator++(int)
Definition RefCountVector.h:417
MappedIterator< int, ToType, IndexIterator > end()
Definition RefCountVector.h:485
MappedEnumerable(const IndexEnumerable &enumerable, TFunction< ToType(int)> MapFunc)
Definition RefCountVector.h:474
MappedIterator< int, ToType, IndexIterator > begin()
Definition RefCountVector.h:480
TFunction< ToType(int)> MapFunc
Definition RefCountVector.h:471
IndexEnumerable enumerable
Definition RefCountVector.h:472
Definition RefCountVector.h:25
FRefCountVector & operator=(FRefCountVector &&From)
Definition RefCountVector.h:37
MappedEnumerable< ToType > MappedIndices(TFunction< ToType(int)> MapFunc) const
Definition RefCountVector.h:497
bool AllocateAt(int Index)
Definition RefCountVector.h:158
friend bool operator==(const FRefCountVector &Lhs, const FRefCountVector &Rhs)
Definition RefCountVector.h:630
TDynamicVector< unsigned short > & GetRawRefCountsUnsafe()
Definition RefCountVector.h:236
FRefCountVector(const FRefCountVector &)=default
void RebuildFreeList()
Definition RefCountVector.h:306
FRefCountVector & operator=(const FRefCountVector &)=default
FString UsageStats() const
Definition RefCountVector.h:532
size_t GetMaxIndex() const
Definition RefCountVector.h:56
static constexpr unsigned short INVALID_REF_COUNT
Definition RefCountVector.h:27
FRefCountVector(FRefCountVector &&From)
Definition RefCountVector.h:31
size_t GetCount() const
Definition RefCountVector.h:51
friend FArchive & operator<<(FArchive &Ar, FRefCountVector &Vec)
Definition RefCountVector.h:550
IndexIterator BeginIndices() const
Definition RefCountVector.h:430
bool IsDense() const
Definition RefCountVector.h:61
void Clear()
Definition RefCountVector.h:332
void Trim(int maxIndex)
Definition RefCountVector.h:325
void Decrement(int Index, unsigned short DecrementCount=1)
Definition RefCountVector.h:139
int GetRefCount(int Index) const
Definition RefCountVector.h:76
void Serialize(FArchive &Ar, bool bCompactData, bool bUseCompression)
Definition RefCountVector.h:562
bool IsValidUnsafe(int Index) const
Definition RefCountVector.h:71
bool AllocateAtUnsafe(int Index)
Definition RefCountVector.h:200
SIZE_T GetByteCount() const
Definition RefCountVector.h:538
void InitDense(int Size, uint16 RefCountValue=1)
Definition RefCountVector.h:340
friend bool operator!=(const FRefCountVector &Lhs, const FRefCountVector &Rhs)
Definition RefCountVector.h:654
const TDynamicVector< unsigned short > & GetRawRefCounts() const
Definition RefCountVector.h:228
int Increment(int Index, unsigned short IncrementCount=1)
Definition RefCountVector.h:132
IndexIterator EndIndices() const
Definition RefCountVector.h:435
void Append(const FRefCountVector &Other)
Definition RefCountVector.h:89
bool IsValid(int Index) const
Definition RefCountVector.h:66
FilteredEnumerable FilteredIndices(TFunction< bool(int)> FilterFunc) const
Definition RefCountVector.h:527
void Rebuild(unsigned int Num, IterateFunc &&Iterate, AllocateRefCountFunc &&AllocateRefCount, IncrementRefCountFunc &&IncrementRefCount)
Definition RefCountVector.h:266
bool IsEmpty() const
Definition RefCountVector.h:46
int Allocate()
Definition RefCountVector.h:102
void SetRefCountUnsafe(int Index, unsigned short ToCount)
Definition RefCountVector.h:244
IndexEnumerable Indices() const
Definition RefCountVector.h:458
int GetRawRefCount(int Index) const
Definition RefCountVector.h:82
Definition IteratorUtil.h:72
Definition IteratorUtil.h:24
Definition DynamicVector.h:27
size_t GetByteCount() const
Definition DynamicVector.h:149
void Add(const Type &Data)
Definition DynamicVector.h:662
const Type & Back() const
Definition DynamicVector.h:167
void PopBack()
Definition DynamicVector.h:717
void Serialize(FArchive &Ar)
Definition DynamicVector.h:794
size_t Num() const
Definition DynamicVector.h:147
void Clear()
Definition DynamicVector.h:578
void Resize(unsigned int Count)
Definition DynamicVector.h:603
bool IsEmpty() const
Definition DynamicVector.h:145
size_t GetLength() const
Definition DynamicVector.h:146
void Fill(const Type &Value)
Definition DynamicVector.h:590
void SetNum(unsigned int Count)
Definition DynamicVector.h:143
Definition AdvancedWidgetsModule.cpp:13
U16 Index
Definition radfft.cpp:71
CORE_API static const FGuid GUID
Definition UE5MainStreamObjectVersion.h:22