UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Handles.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include "Chaos/Core.h"
7#include "ChaosCheck.h"
8
9namespace Chaos
10{
11 template<typename ElementType, uint32 IndexWidth, uint32 GenerationWidth>
12 class THandleArray;
13
14 template<typename ElementType, uint32 IndexWidth, uint32 GenerationWidth>
15 class THandleHeap;
16
17 template<typename ElementType, uint32 IndexWidth, uint32 GenerationWidth>
18 class TConstHandle;
19
20 template<uint32 IndexWidth, uint32 GenerationWidth>
22 {
23 public:
24
25 static_assert((IndexWidth + GenerationWidth) / 8 == sizeof(uint32), "Sum of widths does not match data type");
26
28 : Index(0)
29 , Generation(0)
30 {
31
32 }
33
40
41 // Mainly for serialization of the handle container
48
49 bool IsValid() const
50 {
51 // Default construction is the invalid state
52 return Generation != 0;
53 }
54
55 uint32 AsUint() const
56 {
57 // Shift the index up to fit the generation
59 }
60
62 {
63 return Index;
64 }
65
67 {
69
71 Generation = InUint & ((1 << IndexWidth) - 1);
72 }
73
75 {
76 uint32 Packed = InHandle.AsUint();
77 Ar << Packed;
78 if(Ar.IsLoading())
79 {
80 InHandle.FromUint(Packed);
81 }
82
83 return Ar;
84 }
85
86 protected:
89 };
90
91 template<typename ElementType, uint32 IndexWidth, uint32 GenerationWidth>
117
118 template<typename ElementType, uint32 IndexWidth, uint32 GenerationWidth>
149
150 template<typename ElementType, uint32 IndexWidth = 24, uint32 GenerationWidth = 8>
152 {
153 public:
154
157
158 static constexpr uint32 ElementAlign = alignof(ElementType);
159 static constexpr SIZE_T ElementSize = sizeof(ElementType);
160 static constexpr uint32 ElementGrowth = 4;
161
163
169
175
177 {
178 CopyFrom(Other);
179 return *this;
180 }
181
187
189 : THandleArray(0)
190 {}
191
192 explicit THandleArray(int32 InitialNum)
193 : FreeList(InvalidFreeIndex)
194 , Data(nullptr)
195 , NumData(0)
196 , Capacity(0)
197 , NumActive(0)
198 {
199 if(InitialNum > 0)
200 {
201 Data = (ElementType*)FMemory::Malloc(InitialNum * ElementSize, ElementAlign);
202 NumData = Capacity = InitialNum;
203
204 // Set up handle entries
205 HandleEntries.AddDefaulted(NumData);
206 for(int32 Index = 1; Index < NumData; ++Index)
207 {
208 HandleEntries[Index - 1].NextFree = Index;
209 }
210 FreeList = 0;
211
212 Validity.Add(false, NumData);
213 }
214 }
215
217 {
218 DestroyItems();
219 }
220
221 ElementType* Get(FHandle InHandle) const
222 {
223 if(InHandle.IsValid())
224 {
225 if(Validity.IsValidIndex(InHandle.Index))
226 {
227 if(Validity[InHandle.Index])
228 {
229 const FHandleEntry& Entry = HandleEntries[InHandle.Index];
230 return Entry.Generation == InHandle.Generation ? &(Data[InHandle.Index]) : nullptr;
231 }
232 }
233 else
234 {
235 CHAOS_ENSURE_MSG(false, TEXT("Failed to access handle (%u, %u). NumEntries = %d, NumFlags = %d"), InHandle.Index, InHandle.Generation, HandleEntries.Num(), Validity.Num());
236 }
237 }
238 return nullptr;
239 }
240
241 const ElementType* Get(FConstHandle InHandle) const
242 {
243 if (InHandle.IsValid())
244 {
245 if (Validity.IsValidIndex(InHandle.Index))
246 {
247 if (Validity[InHandle.Index])
248 {
249 const FHandleEntry& Entry = HandleEntries[InHandle.Index];
250 return Entry.Generation == InHandle.Generation ? &(Data[InHandle.Index]) : nullptr;
251 }
252 }
253 else
254 {
255 ensureMsgf(false, TEXT("Failed to access handle (%u, %u). NumEntries = %d, NumFlags = %d"), InHandle.Index, InHandle.Generation, HandleEntries.Num(), Validity.Num());
256 }
257 }
258 return nullptr;
259 }
260
262 {
263 // Only return a handle if we have an entry and it hasn't been retired
264 if(HandleEntries.IsValidIndex(InIndex) && HandleEntries[InIndex].Generation != 0)
265 {
266 return FHandle(InIndex, HandleEntries[InIndex].Generation);
267 }
268
269 return FHandle();
270 }
271
276
277 template<typename... ConstructionArgs>
279 {
280 // Look for free slots
281 int32 NewIndex = INDEX_NONE;
282 if(FreeList != InvalidFreeIndex)
283 {
284 NewIndex = FreeList;
285 FHandleEntry& ReusedEntry = HandleEntries[FreeList];
286 Validity[FreeList] = true;
287 FreeList = ReusedEntry.NextFree;
288 ReusedEntry.NextFree = InvalidFreeIndex;
289 }
290 else
291 {
292 // If nothing in the freelist then proceed to adding new elements
293 if(NumData == Capacity)
294 {
295 // Realloc
296 Data = (ElementType*)FMemory::Realloc(Data, ElementSize * (Capacity + ElementGrowth), ElementAlign);
297 Capacity += ElementGrowth;
298 }
299
300 NewIndex = NumData;
301 HandleEntries.AddDefaulted();
302 Validity.Add(true);
303 ++NumData;
304 }
305
306 new (Data + NewIndex) ElementType(Forward<ConstructionArgs>(InConstructionArgs)...);
307
308 NumActive++;
309 return GetHandle(NewIndex);
310 }
311
313 {
314 if(InHandle.IsValid())
315 {
316 // Get the entry
317 FHandleEntry& Entry = HandleEntries[InHandle.Index];
318
319 if(Entry.Generation != InHandle.Generation)
320 {
321 // Invalid handle no longer points to this resource
322 ensureMsgf(false, TEXT("Attempting to destroy with an invalid handle."));
323 return;
324 }
325
326 // Invalidate it
327 Entry.Generation++;
328
329 // Destruct the element and set the valid flag
330 DestructItem(Data + InHandle.Index);
331 Validity[InHandle.Index] = false;
332 NumActive--;
333
334 if(Entry.Generation == 0)
335 {
336 // If we overflow we have to retire this array slot otherwise there could technically
337 // be collisions with old handles.
338 return;
339 }
340
341 // If we should reuse this slot, handle the freelist
342 if(FreeList != InvalidFreeIndex)
343 {
344 HandleEntries[InHandle.Index].NextFree = FreeList;
345 FreeList = InHandle.Index;
346 }
347 else
348 {
349 FreeList = InHandle.Index;
350 }
351 }
352 }
353
354 uint32 Num() const
355 {
356 return NumData;
357 }
358
360 {
361 return Capacity;
362 }
363
365 {
366 return NumActive;
367 }
368
370 {
371 return Num() - NumActive;
372 }
373
375 {
376 Ar << Array.FreeList << Array.HandleEntries << Array.Validity << Array.NumData << Array.Capacity << Array.NumActive;
377
378 // Need to serialize per element as T.<< could serialize out-of-order
379 if(Ar.IsLoading())
380 {
381 Array.Data = (ElementType*)FMemory::Realloc(Array.Data, Array.Capacity * ElementSize, ElementAlign);
382 for(int32 Index = 0; Index < Array.NumData; ++Index)
383 {
384 Array.Data[Index] = ElementType();
385 Ar << Array.Data[Index];
386 }
387 }
388 else
389 {
390 for(int32 Index = 0; Index < Array.NumData; ++Index)
391 {
392 Ar << Array.Data[Index];
393 }
394 }
395
396 return Ar;
397 }
398
399 template<bool bConst>
401 {
402 typedef std::conditional_t<bConst, const THandleArray, THandleArray> ArrayType;
403 typedef std::conditional_t<bConst, const ElementType, ElementType> ItElementType;
404
406 : Array(InArray)
407 , It(InArray.Validity, InIndex)
408 {
409 }
410
412 {
413 // Iterate to the next set allocation flag.
414 ++It;
415 return *this;
416 }
417
418 [[nodiscard]] FORCEINLINE bool operator==(const TIterator& Rhs) const
419 {
420 return It == Rhs.It && &Array == &Rhs.Array;
421 }
422
423 [[nodiscard]] FORCEINLINE bool operator!=(const TIterator& Rhs) const
424 {
425 return It != Rhs.It || &Array != &Rhs.Array;
426 }
427
429 {
430 const int32 Index = It.GetIndex();
431 return Array.GetConstHandle(Index);
432 }
433
435 {
436 const int32 Index = It.GetIndex();
437 return Array.GetHandle(Index);
438 }
439
441 {
442 const FHandle Handle = GetHandle();
443 ItElementType* Element = Array.Get(Handle);
444 return *Element;
445 }
446
448 {
449 const FHandle Handle = GetHandle();
450 return Array.Get(Handle);
451 }
452
455 };
456
459
461 {
462 return TRangedForIterator(*this, 0);
463 }
464
466 {
467 return TRangedForConstIterator(*this, 0);
468 }
469
471 {
472 return TRangedForIterator(*this, (int32)Num());
473 }
474
476 {
477 return TRangedForConstIterator(*this, (int32)Num());
478 }
479
480 private:
481
482 void DestroyItems()
483 {
484 if(Data)
485 {
486 for(int32 Index = 0; Index < NumData; ++Index)
487 {
488 if(Validity[Index])
489 {
490 DestructItem(Data + Index);
491 }
492 }
493
494 FMemory::Free(Data);
495 }
496
497 FreeList = InvalidFreeIndex;
498 Capacity = 0;
499 NumData = 0;
500 NumActive = 0;
501 Data = nullptr;
502 Validity.Reset();
503 HandleEntries.Reset();
504 }
505
506 void CopyFrom(const THandleArray& Other)
507 {
508 DestroyItems();
509
510 Capacity = Other.Capacity;
511 HandleEntries = Other.HandleEntries;
512 Validity = Other.Validity;
513 FreeList = Other.FreeList;
514
515 if(Capacity > 0)
516 {
517 Data = (ElementType*)FMemory::Malloc(Capacity * ElementSize, ElementAlign);
518
519 NumData = Other.NumData;
520 NumActive = Other.NumActive;
521
522 for(int32 Index = 0; Index < NumData; ++Index)
523 {
524 if(Validity[Index])
525 {
526 ConstructItems<ElementType>(Data + Index, Other.Data + Index, 1);
527 }
528 }
529 }
530 }
531
532 void MoveFrom(THandleArray& Other)
533 {
534 DestroyItems();
535
536 Capacity = Other.Capacity;
537
538 if(Capacity > 0)
539 {
540 Data = MoveTemp(Other.Data);
541
542 NumData = Other.NumData;
543 NumActive = Other.NumActive;
544 }
545
546 HandleEntries = MoveTemp(Other.HandleEntries);
547 Validity = MoveTemp(Other.Validity);
548
549 FreeList = Other.FreeList;
550
551 // This container now owns the allocation from Other
552 Other.FreeList = InvalidFreeIndex;
553 Other.Capacity = 0;
554 Other.NumData = 0;
555 Other.NumActive = 0;
556 Other.Data = nullptr;
557 }
558
559 class FHandleEntry
560 {
561 public:
562
563 FHandleEntry()
564 : NextFree(InvalidFreeIndex)
565 , Generation(1)
566 {
567
568 }
569
570 uint32 NextFree : IndexWidth;
571 uint32 Generation : GenerationWidth;
572
573 friend FArchive& operator << (FArchive& Ar, FHandleEntry& InHandleEntry)
574 {
575 uint32 Packed = InHandleEntry.NextFree << GenerationWidth | InHandleEntry.Generation;
576 Ar << Packed;
577
578 if(Ar.IsLoading())
579 {
580 InHandleEntry.NextFree = Packed >> GenerationWidth;
581 InHandleEntry.Generation = Packed & ((1 << IndexWidth) - 1);
582 }
583
584 return Ar;
585 }
586 };
587
588 uint32 FreeList;
589 TArray<FHandleEntry> HandleEntries;
590 TBitArray<> Validity;
591 ElementType* Data;
592 int32 NumData;
593 int32 Capacity;
594 int32 NumActive;
595 };
596
597 template<typename ElementType, uint32 IndexWidth = 24, uint32 GenerationWidth = 8>
599 {
600 public:
601
602 static_assert(TIsTrivial<ElementType>::Value, "Handle managed data must be trivial");
603
605 using FConstHandle = TConstHandle < ElementType, IndexWidth, GenerationWidth>;
606
608
610 : FreeList(InvalidFreeIndex)
611 , NumActive(0)
612 {
613 HandleEntries.Reserve(ReserveNum);
614 }
615
621
626
628 {
629 CopyFrom(Other);
630 return *this;
631 }
632
638
640 : THandleHeap(0)
641 {}
642
644 {
645 Empty();
646 }
647
648 ElementType* Get(FHandle InHandle)
649 {
650 FHandleEntry& Entry = HandleEntries[InHandle.Index];
651 return (Entry.Generation == InHandle.Generation && Validity[InHandle.Index]) ? Entry.Ptr : nullptr;
652 }
653
654 const ElementType* Get(FConstHandle InHandle) const
655 {
656 const FHandleEntry& Entry = HandleEntries[InHandle.Index];
657 return (Entry.Generation == InHandle.Generation && Validity[InHandle.Index]) ? Entry.Ptr : nullptr;
658 }
659
661 {
662 // Only return a handle if we have an entry and it hasn't been retired
663 if(HandleEntries.IsValidIndex(InIndex) && HandleEntries[InIndex].Generation != 0)
664 {
665 return FHandle(InIndex, HandleEntries[InIndex].Generation);
666 }
667
668 return FHandle();
669 }
670
675
676 template<typename... ConstructionArgs>
678 {
679 int32 NewIndex = INDEX_NONE;
680 if(FreeList != InvalidFreeIndex)
681 {
682 NewIndex = FreeList;
683 FHandleEntry& ReusedEntry = HandleEntries[FreeList];
684 ReusedEntry.Ptr = new ElementType(Forward<ConstructionArgs>(Args)...);
685 Validity[FreeList] = true;
686 FreeList = ReusedEntry.NextFree;
687 ReusedEntry.NextFree = InvalidFreeIndex;
688 }
689 else
690 {
691 HandleEntries.AddDefaulted();
692 Validity.Add(true);
693
694 FHandleEntry& NewEntry = HandleEntries.Last();
695 NewEntry.Ptr = new ElementType(Forward<ConstructionArgs>(Args)...);
696 NewIndex = HandleEntries.Num() - 1;
697 }
698
699 NumActive++;
700 return GetHandle(NewIndex);
701 }
702
704 {
705 if(InHandle.IsValid())
706 {
707 FHandleEntry& Entry = HandleEntries[InHandle.Index];
708
709 if(Entry.Generation != InHandle.Generation)
710 {
711 // Bail if this handle is out of date - it doesn't point to this resource
712 ensureMsgf(false, TEXT("Attempting to destroy with an invalid handle."));
713 return;
714 }
715
716 // Invalidate
717 Entry.Generation++;
718 Validity[InHandle.Index] = false;
719
720 if(Entry.Ptr)
721 {
722 // If the state of this container has been moved to another then
723 // this ptr will be nullptr
724 delete Entry.Ptr;
725 Entry.Ptr = nullptr;
726 NumActive--;
727 }
728
729 if(Entry.Generation == 0)
730 {
731 // If we overflow we have to retire this array slot otherwise there could technically
732 // be collisions with old handles.
733 return;
734 }
735
736 // If we should reuse this slot, handle the freelist
737 if(FreeList != InvalidFreeIndex)
738 {
739 HandleEntries[InHandle.Index].NextFree = FreeList;
740 FreeList = InHandle.Index;
741 }
742 else
743 {
744 FreeList = InHandle.Index;
745 }
746 }
747 }
748
749 int32 Num() const
750 {
751 return HandleEntries.Num();
752 }
753
755 {
756 return NumActive;
757 }
758
759 void Empty(bool bShrink = true)
760 {
761 // Destruct all the elements (every existing entry will be added to the freelist)
762 const int32 NumToRemove = Num();
763 for(int32 Index = 0; Index < NumToRemove; ++Index)
764 {
766 }
767
768 HandleEntries.Empty(bShrink ? 0 : HandleEntries.GetAllocatedSize());
769 Validity.Empty();
770 FreeList = InvalidFreeIndex;
771 }
772
774 {
775 Ar << Array.FreeList << Array.HandleEntries << Array.Validity << Array.NumActive;
776
777 // Need to serialize per element as T.<< could serialize out-of-order
778 const int32 NumEntries = Array.HandleEntries.Num();
779 if(Ar.IsLoading())
780 {
781 for(int32 Index = 0; Index < NumEntries; ++Index)
782 {
783 if(!Array.Validity[Index])
784 {
785 continue;
786 }
787
788 FHandleEntry& Entry = Array.HandleEntries[Index];
789 Entry.Ptr = new ElementType();
790 Ar << *Entry.Ptr;
791 }
792 }
793 else
794 {
795 for(int32 Index = 0; Index < NumEntries; ++Index)
796 {
797 if(!Array.Validity[Index])
798 {
799 continue;
800 }
801
802 FHandleEntry& Entry = Array.HandleEntries[Index];
803 Ar << *Entry.Ptr;
804 }
805 }
806
807 return Ar;
808 }
809
810 private:
811
813 {
814 Empty();
815
816 FreeList = Other.FreeList;
817 NumActive = Other.NumActive;
818 Validity = Other.Validity;
819
820 HandleEntries.Reserve(Other.Num());
821 for(const FHandleEntry& Entry : Other.HandleEntries)
822 {
823 HandleEntries.AddDefaulted();
824 FHandleEntry& NewEntry = HandleEntries.Last();
825 NewEntry.NextFree = Entry.NextFree;
826 NewEntry.Generation = Entry.Generation;
827 NewEntry.Ptr = Entry.Ptr ? new ElementType(*Entry.Ptr) : nullptr;
828 }
829 }
830
831 void MoveFrom(THandleHeap<ElementType, IndexWidth, GenerationWidth>& Other)
832 {
833 Empty();
834
835 FreeList = Other.FreeList;
836 NumActive = Other.NumActive;
837
838 Validity = MoveTemp(Other.Validity);
839 HandleEntries = MoveTemp(Other.HandleEntries);
840
841 // Clear out all the handle entries in the other container.
842 Other.Empty();
843 Other.NumActive = 0;
844 }
845
846 class FHandleEntry
847 {
848 public:
849
850 FHandleEntry()
851 : NextFree(InvalidFreeIndex)
852 , Generation(1)
853 , Ptr(nullptr)
854 {
855
856 }
857
858 uint32 NextFree : IndexWidth;
859 uint32 Generation : GenerationWidth;
860 ElementType* Ptr;
861
862 friend FArchive& operator << (FArchive& Ar, FHandleEntry& InHandleEntry)
863 {
864 uint32 Packed = InHandleEntry.NextFree << GenerationWidth | InHandleEntry.Generation;
865 Ar << Packed;
866
867 if(Ar.IsLoading())
868 {
869 InHandleEntry.NextFree = Packed >> GenerationWidth;
870 InHandleEntry.Generation = Packed & ((1 << IndexWidth) - 1);
871 }
872
873 return Ar;
874 }
875 };
876
877 uint32 FreeList;
878 TArray<FHandleEntry> HandleEntries;
879 TBitArray<> Validity;
880 int32 NumActive;
881 };
882}
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define CHAOS_ENSURE_MSG(InExpression, InFormat,...)
Definition ChaosCheck.h:23
@ 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
FORCEINLINE constexpr void DestructItem(ElementType *Element)
Definition MemoryOps.h:56
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ChaosArchive.h:167
Definition Handles.h:120
TConstHandle(const THandle< ElementType, IndexWidth, GenerationWidth > &InNonConstHandle)
Definition Handles.h:132
TConstHandle()=default
friend FArchive & operator<<(FArchive &Ar, TConstHandle< ElementType, IndexWidth, GenerationWidth > &InHandle)
Definition Handles.h:143
TConstHandle(uint32 InIndex, uint32 InGeneration)
Definition Handles.h:126
friend bool operator==(const TConstHandle< ElementType, IndexWidth, GenerationWidth > &A, const TConstHandle< ElementType, IndexWidth, GenerationWidth > &B)
Definition Handles.h:138
Definition Handles.h:152
static constexpr uint32 InvalidFreeIndex
Definition Handles.h:162
TRangedForConstIterator begin() const
Definition Handles.h:465
uint32 Num() const
Definition Handles.h:354
void Destroy(FHandle InHandle)
Definition Handles.h:312
~THandleArray()
Definition Handles.h:216
FHandle GetHandle(uint32 InIndex) const
Definition Handles.h:261
TRangedForIterator end()
Definition Handles.h:470
TRangedForConstIterator end() const
Definition Handles.h:475
TRangedForIterator begin()
Definition Handles.h:460
uint32 GetNumActive() const
Definition Handles.h:364
TIterator< true > TRangedForConstIterator
Definition Handles.h:458
THandleArray(int32 InitialNum)
Definition Handles.h:192
uint32 GetCapacity() const
Definition Handles.h:359
TConstHandle< ElementType, IndexWidth, GenerationWidth > FConstHandle
Definition Handles.h:156
TIterator< false > TRangedForIterator
Definition Handles.h:457
THandleArray(const THandleArray< ElementType, IndexWidth, GenerationWidth > &Other)
Definition Handles.h:164
THandleArray()
Definition Handles.h:188
THandleArray(THandleArray< ElementType, IndexWidth, GenerationWidth > &&Other)
Definition Handles.h:170
FConstHandle GetConstHandle(uint32 InIndex) const
Definition Handles.h:272
static constexpr uint32 ElementAlign
Definition Handles.h:158
friend FChaosArchive & operator<<(FChaosArchive &Ar, THandleArray &Array)
Definition Handles.h:374
static constexpr SIZE_T ElementSize
Definition Handles.h:159
THandle< ElementType, IndexWidth, GenerationWidth > FHandle
Definition Handles.h:155
static constexpr uint32 ElementGrowth
Definition Handles.h:160
FHandle Create(ConstructionArgs &&... InConstructionArgs)
Definition Handles.h:278
ElementType * Get(FHandle InHandle) const
Definition Handles.h:221
const ElementType * Get(FConstHandle InHandle) const
Definition Handles.h:241
THandleArray & operator=(const THandleArray< ElementType, IndexWidth, GenerationWidth > &Other)
Definition Handles.h:176
uint32 GetNumFree() const
Definition Handles.h:369
Definition Handles.h:22
uint32 Generation
Definition Handles.h:88
uint32 GetIndex() const
Definition Handles.h:61
THandleData(uint32 InIndex, uint32 InGeneration)
Definition Handles.h:34
uint32 Index
Definition Handles.h:87
bool IsValid() const
Definition Handles.h:49
uint32 AsUint() const
Definition Handles.h:55
THandleData()
Definition Handles.h:27
void FromUint(uint32 InUint)
Definition Handles.h:66
friend FArchive & operator<<(FArchive &Ar, THandleData< IndexWidth, GenerationWidth > &InHandle)
Definition Handles.h:74
THandleData(uint32 FullHandle)
Definition Handles.h:42
Definition Handles.h:599
TConstHandle< ElementType, IndexWidth, GenerationWidth > FConstHandle
Definition Handles.h:605
void Empty(bool bShrink=true)
Definition Handles.h:759
FHandle Create(ConstructionArgs... Args)
Definition Handles.h:677
const ElementType * Get(FConstHandle InHandle) const
Definition Handles.h:654
THandleHeap(const THandleHeap< ElementType, IndexWidth, GenerationWidth > &Other)
Definition Handles.h:616
friend FArchive & operator<<(FArchive &Ar, THandleHeap &Array)
Definition Handles.h:773
THandleHeap & operator=(const THandleHeap< ElementType, IndexWidth, GenerationWidth > &Other)
Definition Handles.h:627
THandleHeap(THandleHeap< ElementType, IndexWidth, GenerationWidth > &&Other)
Definition Handles.h:622
FConstHandle GetConstHandle(uint32 InIndex)
Definition Handles.h:671
THandleHeap()
Definition Handles.h:639
FHandle GetHandle(uint32 InIndex)
Definition Handles.h:660
~THandleHeap()
Definition Handles.h:643
ElementType * Get(FHandle InHandle)
Definition Handles.h:648
void Destroy(FHandle InHandle)
Definition Handles.h:703
static constexpr uint32 InvalidFreeIndex
Definition Handles.h:607
int32 GetNumActive() const
Definition Handles.h:754
THandle< ElementType, IndexWidth, GenerationWidth > FHandle
Definition Handles.h:604
THandleHeap(int32 ReserveNum)
Definition Handles.h:609
int32 Num() const
Definition Handles.h:749
Definition Handles.h:93
THandle()=default
THandle(uint32 InIndex, uint32 InGeneration)
Definition Handles.h:100
friend FArchive & operator<<(FArchive &Ar, THandle< ElementType, IndexWidth, GenerationWidth > &InHandle)
Definition Handles.h:111
friend bool operator==(const THandle< ElementType, IndexWidth, GenerationWidth > &A, const THandle< ElementType, IndexWidth, GenerationWidth > &B)
Definition Handles.h:106
Definition Archive.h:1208
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT ElementType & Last(SizeType IndexFromTheEnd=0) UE_LIFETIMEBOUND
Definition Array.h:1263
void Reset(SizeType NewSize=0)
Definition Array.h:2246
SizeType AddDefaulted()
Definition Array.h:2795
UE_NODEBUG UE_FORCEINLINE_HINT bool IsValidIndex(SizeType Index) const
Definition Array.h:1122
UE_NODEBUG UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize(void) const
Definition Array.h:1059
void Empty(SizeType Slack=0)
Definition Array.h:2273
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
UE_FORCEINLINE_HINT int32 Num() const
Definition BitArray.h:1466
UE_FORCEINLINE_HINT bool IsValidIndex(int32 InIndex) const
Definition BitArray.h:1450
int32 Add(const bool Value)
Definition BitArray.h:615
void Empty(int32 ExpectedNumBits=0)
Definition BitArray.h:779
void Reset()
Definition BitArray.h:817
Definition BitArray.h:1944
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition BitArray.h:2011
Definition SkeletalMeshComponent.h:307
U16 Index
Definition radfft.cpp:71
Definition Handles.h:401
FORCEINLINE TIterator & operator++()
Definition Handles.h:411
FConstHandle GetConstHandle() const
Definition Handles.h:428
TConstSetBitIterator It
Definition Handles.h:454
TIterator(ArrayType &InArray, int32 InIndex)
Definition Handles.h:405
FORCEINLINE ItElementType & operator*() const
Definition Handles.h:440
FHandle GetHandle() const
Definition Handles.h:434
std::conditional_t< bConst, const ElementType, ElementType > ItElementType
Definition Handles.h:403
ArrayType & Array
Definition Handles.h:453
FORCEINLINE bool operator!=(const TIterator &Rhs) const
Definition Handles.h:423
std::conditional_t< bConst, const THandleArray, THandleArray > ArrayType
Definition Handles.h:402
FORCEINLINE bool operator==(const TIterator &Rhs) const
Definition Handles.h:418
FORCEINLINE ItElementType * operator->() const
Definition Handles.h:447
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685
Definition IsTrivial.h:15
Definition NumericLimits.h:41