UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
UObjectArray.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 UObjectArray.h: Unreal object array
5=============================================================================*/
6
7#pragma once
8
9#include "AutoRTFM.h"
12#include "Misc/ScopeLock.h"
15#include "UObject/UObjectBase.h"
16
17#if WITH_VERSE_VM || defined(__INTELLISENSE__)
18namespace Verse
19{
20 struct VCell;
21}
22#endif
23
24#ifndef UE_PACK_FUOBJECT_ITEM
25# define UE_ENABLE_FUOBJECT_ITEM_PACKING 0
26#elif PLATFORM_CPU_ARM_FAMILY && FORCE_ANSI_ALLOCATOR
27// disable packing on ARM64 is we use Ansi allocator as it might use MTE or HWASan which uses top byte of a pointer and this feature will discard that
28# define UE_ENABLE_FUOBJECT_ITEM_PACKING 0
29#else
30# define UE_ENABLE_FUOBJECT_ITEM_PACKING UE_PACK_FUOBJECT_ITEM && !UE_WITH_REMOTE_OBJECT_HANDLE
31#endif
32
37#if !defined(UE_GC_TRACK_OBJ_AVAILABLE)
38#define UE_GC_TRACK_OBJ_AVAILABLE UE_DEPRECATED_MACRO(5.2, "The UE_GC_TRACK_OBJ_AVAILABLE macro has been deprecated because it is no longer necessary.") 1
39#endif
40
41namespace UE::GC::Private
42{
43 class FGCFlags;
44}
45
50{
51 friend class FUObjectArray;
53
54private:
55 // Stores EInternalObjectFlags (and higher 13 bits of the UObject pointer packed together if UE_PACK_FUOBJECT_ITEM is set to 1)
56 // These can only be changed via Set* and Clear* functions
57 // The Flags are now stored on high 32-bit so that we can use InterlockedInc/InterlockedDec directly for RefCount which is stored on the low 32-bit
58 // while preserving atomicity of the whole thing so RootFlags+RefCount can be evaluated in a lock-less way.
59 // If we want to add more Flags, we can reduce the size of RefCount to 24 bits to give us more bits for Flags but will require that we convert
60 // EInternalObjectFlags to a 64-bit.
61 union
62 {
64#if !UE_WITH_REMOTE_OBJECT_HANDLE
65 // Dummy variable for natvis
67#endif
68 };
69
70#if !UE_ENABLE_FUOBJECT_ITEM_PACKING
71public:
72 union
73 {
74 // Pointer to the allocated object
75 UE_DEPRECATED(5.6, "Use GetObject() and SetObject() to access Object.")
76 class UObjectBase* Object = nullptr;
77 uint32 ObjectPtrLow; // this one is used as a dummy for natvis only an will be removed once packing will be enabled by default
78 };
79#else
80 union
81 {
82 // Stores lower 32 bits of UObject pointer shifted by 3 to the left as all our allocations are at least 8 bytes aligned and lower 3 bits will always be 0
84 uint32 Object; // this one is used as a dummy for natvis only an will be removed once packing will be enabled by default
85 };
86#endif
87private:
88 // Currently we assume UObjects are aligned by 8 bytes, that gives us 3 lower bits as zeros that we can discard.
89 // This will give us total 45 bits in a pointer that we pack into a int32 and the remaining 13 bits we pack with Flags
90 // EInternalObjectFlags_MinFlagBitIndex at the time of writing this is 14 and we have only 1 bit left in the EInternalObjectFlags for future use
91 // We can increase UObject alignment to 16 bytes to get one more bit and reduce the overall addressable virtual memory range to get more bits if necessary
92 constexpr static int32 UObjectAlignment = 8;
93 constexpr static int32 UObjectPtrTrailingZeroes = FMath::CountTrailingZeros(UObjectAlignment);
94 static_assert(int(EInternalObjectFlags_MinFlagBitIndex) >= 48 - 32 - UObjectPtrTrailingZeroes, "We need at least 13 bits to pack higher bits of a UObject pointer into Flags");
95 constexpr static int32 FlagsMask = 0xFFFFFFFF << int(EInternalObjectFlags_MinFlagBitIndex);
96 constexpr static int32 PtrMask = ~FlagsMask;
97
98public:
99 // Weak Object Pointer Serial number associated with the object
101 // UObject Owner Cluster Index
103
104#if UE_WITH_REMOTE_OBJECT_HANDLE
105private:
106 // Globally unique id of this object
108public:
109#endif
110
111#if STATS || ENABLE_STATNAMEDEVENTS_UOBJECT
113 mutable TStatId StatID;
114
115#if ENABLE_STATNAMEDEVENTS_UOBJECT
117#endif
118#endif // STATS || ENABLE_STATNAMEDEVENTS
119
130 {
131#if ENABLE_STATNAMEDEVENTS_UOBJECT
132 if (PROFILER_CHAR* Storage = StatIDStringStorage)
133 {
134 AutoRTFM::PopOnAbortHandler(Storage);
135 delete[] Storage;
136 }
137#endif
138 }
139
140 // Non-copyable
142 FUObjectItem(const FUObjectItem&) = delete;
145
146 inline class UObjectBase* GetObject() const
147 {
148#if UE_ENABLE_FUOBJECT_ITEM_PACKING
149 const uintptr_t Obj = (uintptr_t((FlagsAndRefCount >> 32) & PtrMask) << (32 + UObjectPtrTrailingZeroes)) | (uintptr_t(ObjectPtrLow) << UObjectPtrTrailingZeroes);
150 return (class UObjectBase*)Obj;
151#else
153 return Object;
155#endif
156 }
157
158 inline void SetObject(class UObjectBase* InObject)
159 {
160#if UE_ENABLE_FUOBJECT_ITEM_PACKING
161 const uint32 ObjectPtrHi = ((uintptr_t)InObject & 0xFFFF00000000ULL) >> (32 + UObjectPtrTrailingZeroes);
162 // This is not thread-safe, so SetObject should ever just be allowed at UObject creation time.
164 ObjectPtrLow = ((uintptr_t)InObject >> UObjectPtrTrailingZeroes) & 0xFFFFFFFF;
165#else
167 Object = InObject;
169#endif
170 }
171
173 {
174 ClusterRootIndex = OwnerIndex;
175 }
176
181
187
189 inline int32 GetClusterIndex() const
190 {
192 return -ClusterRootIndex - 1;
193 }
194
195 inline int32 GetSerialNumber() const
196 {
197 // AutoRTFM doesn't like atomics even when relaxed, so we need to differentiate the code here
198#if USING_INSTRUMENTATION || USING_THREAD_SANITISER
199 // Resolving an old WeakPtr can race with new object construction.
200 // Use a relaxed atomic here so that TSAN knows this is considered safe.
201 return FPlatformAtomics::AtomicRead_Relaxed(&SerialNumber);
202#else
203 return SerialNumber;
204#endif
205 }
206
207#if UE_WITH_REMOTE_OBJECT_HANDLE
209 {
210 RemoteId = Id.GetLocalized();
211 }
212 UE_FORCEINLINE_HINT FRemoteObjectId GetRemoteId() const
213 {
214 return RemoteId;
215 }
216#endif // UE_WITH_REMOTE_OBJECT_HANDLE
217
222
224 {
225#if UE_ENABLE_FUOBJECT_ITEM_PACKING
226 return EInternalObjectFlags(GetFlagsInternal() & FlagsMask);
227#else
228 return EInternalObjectFlags(GetFlagsInternal());
229#endif
230 }
231
236
243 {
244 checkf((int32(FlagToClear) & ~int32(EInternalObjectFlags_AllFlags)) == 0, TEXT("%d is not a valid internal flag value"), int32(FlagToClear));
245 bool bIChangedIt = false;
246
248 {
249 FlagToClear &= ~EInternalObjectFlags_ReachabilityFlags; // reachability flags can only be cleared by GC through *_ForGC functions
251 {
252 bIChangedIt = ClearRootFlags(FlagToClear);
253 }
254 else
255 {
256 bIChangedIt = AtomicallyClearFlag_ForGC(FlagToClear);
257 }
258 };
259
260 if (bIChangedIt)
261 {
262 // If we abort we undo clearing the flags we just set because `bIChangedIt` being true tells us that we were the ones who cleared the flag.
263 // #jira SOL-8462: this could potentially undo flag changes made on a separate thread if an abort occurs.
265 {
267 };
268 }
269
270 return bIChangedIt;
271 }
272
279 {
280 checkf((int32(FlagToSet) & ~int32(EInternalObjectFlags_AllFlags)) == 0, TEXT("%d is not a valid internal flag value"), int32(FlagToSet));
281 bool bIChangedIt = false;
282
284 {
285 FlagToSet &= ~EInternalObjectFlags_ReachabilityFlags; // reachability flags can only be cleared by GC through *_ForGC functions
287 {
288 bIChangedIt = SetRootFlags(FlagToSet);
289 }
290 else
291 {
292 bIChangedIt = AtomicallySetFlag_ForGC(FlagToSet);
293 }
294 };
295
296 if (bIChangedIt)
297 {
298 // If we abort we undo setting the flags we just set because `bIChangedIt` being true tells us that we were the ones who set the flag.
299 // #jira SOL-8462: this could potentially undo flag changes made on a separate thread if an abort occurs.
301 {
303 };
304 }
305
306 return bIChangedIt;
307 }
308
310 {
311 return !!(GetFlagsInternal() & int32(InFlags));
312 }
313
315 {
316 return (GetFlagsInternal() & int32(InFlags)) == int32(InFlags);
317 }
318
320 {
321 return !!(GetFlagsInternal() & int32(EInternalObjectFlags::Unreachable));
322 }
323
333 {
334 return !!(GetFlagsInternal() & int32(EInternalObjectFlags::Garbage));
335 }
336
346 {
347 return !!(GetFlagsInternal() & int32(EInternalObjectFlags::RootSet));
348 }
349
354
355 void AddRef()
356 {
358 {
359 const int64 NewRefCount = FPlatformAtomics::InterlockedIncrement(&FlagsAndRefCount);
360
361 // Only dirty root when doing a transition from no root flags to a refcount.
363 {
365 {
366 // Setting any of the root flags on an object during incremental reachability requires a GC barrier
367 // to make sure an object with root flags does not get Garbage Collected
368 checkf(GetObject(), TEXT("Setting an internal object flag on a null object entry"));
370 }
371
372 MarkRootAsDirty();
373 }
374 };
375
376 // If the transaction is aborted we need to remember to release the reference we added in the open!
378 {
379 this->ReleaseRef();
380 };
381 }
382
384 {
386 {
387 // Only dirty root when doing a transition from a refcount to no refcounts and no other root flags present.
388 const int64 NewRefCount = FPlatformAtomics::InterlockedDecrement(&FlagsAndRefCount);
391 {
392 MarkRootAsDirty();
393 }
394 };
395
396 // If the transaction is aborted we need to remember to re-add the reference we released in the open!
397 // Note: this is different to how we handle ref counts in general in UE. Elsewhere we will eagerly
398 // increment ref counts, but delay decrement. This is because `0` is normally the 'destroy the object'
399 // trigger. But for UObject's `0` just clears the `RefCounted` flag, and since GC cannot run between
400 // when we clear the flag and potentially re-add the flag below, the GC couldn't observe the state
401 // that the object wasn't being actively ref-counted and thus could be collected. We do it differently
402 // here because a bunch of the UObject systems depend on the ref count being correct after calls to
403 // add/release.
405 {
406 this->AddRef();
407 };
408 }
409
410#if STATS || ENABLE_STATNAMEDEVENTS_UOBJECT
411 COREUOBJECT_API void CreateStatID() const;
412#endif
413
414private:
415 UE_FORCEINLINE_HINT static int32 GetFlagsInternal(int64 FlagsAndRefCount)
416 {
417 return (int32)(FlagsAndRefCount >> 32);
418 }
419
420 UE_FORCEINLINE_HINT int32 GetFlagsInternal() const
421 {
422 return GetFlagsInternal(FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount));
423 }
424
425 UE_FORCEINLINE_HINT static int32 GetRefCountInternal(int64 FlagsAndRefCount)
426 {
428 }
429
430 UE_FORCEINLINE_HINT int32 GetRefCountInternal() const
431 {
432 return GetRefCountInternal(FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount));
433 }
434
435 COREUOBJECT_API void MarkRootAsDirty();
438
444 inline bool AtomicallySetFlag_ForGC(EInternalObjectFlags FlagToSet)
445 {
446 static_assert(sizeof(int64) == sizeof(FlagsAndRefCount), "Flags must be 64-bit for atomics.");
447 bool bIChangedIt = false;
448 while (true)
449 {
450 const int64 StartValue = FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount);
451 const int32 StartFlagsValue = GetFlagsInternal(StartValue);
453 {
454 break;
455 }
457 const int64 NewValue = ((int64)NewFlagsValue << 32) | GetRefCountInternal(StartValue);
458 if (FPlatformAtomics::InterlockedCompareExchange((int64*)&FlagsAndRefCount, NewValue, StartValue) == StartValue)
459 {
460 bIChangedIt = true;
461 break;
462 }
463 }
464 return bIChangedIt;
465 }
466
474 inline bool AtomicallySetFlag_ForGC(EInternalObjectFlags FlagToSet, int32& OldFlags, int32& OldRefCount)
475 {
476 static_assert(sizeof(int64) == sizeof(FlagsAndRefCount), "Flags must be 64-bit for atomics.");
477 bool bIChangedIt = false;
478 while (true)
479 {
480 const int64 StartValue = FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount);
481 const int32 StartFlagsValue = GetFlagsInternal(StartValue);
483 {
484 OldFlags = StartFlagsValue;
485 OldRefCount = GetRefCountInternal(StartValue);
486 break;
487 }
489 const int64 NewValue = ((int64)NewFlagsValue << 32) | GetRefCountInternal(StartValue);
490 if (FPlatformAtomics::InterlockedCompareExchange((int64*)&FlagsAndRefCount, NewValue, StartValue) == StartValue)
491 {
492 OldFlags = StartFlagsValue;
493 OldRefCount = GetRefCountInternal(StartValue);
494 bIChangedIt = true;
495 break;
496 }
497 }
498 return bIChangedIt;
499 }
500
506 inline bool AtomicallyClearFlag_ForGC(EInternalObjectFlags FlagToClear)
507 {
508 static_assert(sizeof(int64) == sizeof(FlagsAndRefCount), "Flags must be 64-bit for atomics.");
509 bool bIChangedIt = false;
510 while (true)
511 {
512 const int64 StartValue = FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount);
513 const int32 StartFlagsValue = GetFlagsInternal(StartValue);
515 {
516 break;
517 }
519 const int64 NewValue = ((int64)NewFlagsValue << 32) | GetRefCountInternal(StartValue);
520 if (FPlatformAtomics::InterlockedCompareExchange((int64*)&FlagsAndRefCount, NewValue, StartValue) == StartValue)
521 {
522 bIChangedIt = true;
523 break;
524 }
525 }
526 return bIChangedIt;
527 }
528
536 inline bool AtomicallyClearFlag_ForGC(EInternalObjectFlags FlagToClear, int32& OldFlags, int32& OldRefCount)
537 {
538 static_assert(sizeof(int64) == sizeof(FlagsAndRefCount), "Flags must be 64-bit for atomics.");
539 bool bIChangedIt = false;
540 while (true)
541 {
542 const int64 StartValue = FPlatformAtomics::AtomicRead_Relaxed((int64*)&FlagsAndRefCount);
543 const int32 StartFlagsValue = GetFlagsInternal(StartValue);
545 {
546 OldFlags = StartFlagsValue;
547 OldRefCount = GetRefCountInternal(StartValue);
548 break;
549 }
551 const int64 NewValue = ((int64)NewFlagsValue << 32) | GetRefCountInternal(StartValue);
552 if (FPlatformAtomics::InterlockedCompareExchange((int64*)&FlagsAndRefCount, NewValue, StartValue) == StartValue)
553 {
554 OldFlags = StartFlagsValue;
555 OldRefCount = GetRefCountInternal(StartValue);
556 bIChangedIt = true;
557 break;
558 }
559 }
560 return bIChangedIt;
561 }
562};
563
576
577
582{
584 TSAN_ATOMIC(FUObjectItem*) Objects;
586 TSAN_ATOMIC(int32) MaxElements;
588 TSAN_ATOMIC(int32) NumElements;
589
590public:
591
593 : Objects(nullptr)
594 , MaxElements(0)
595 , NumElements(0)
596 {
597 }
598
600 {
601 delete [] Objects;
602 }
603
609 {
610 check(!Objects);
611 Objects = new FUObjectItem[InMaxElements];
612 MaxElements = InMaxElements;
613 }
614
616 {
617 int32 Result = NumElements;
618 UE::UObjectArrayPrivate::CheckUObjectLimitReached(NumElements, MaxElements, 1);
619 check(Result == NumElements);
620 ++NumElements;
622 check(Objects[Result].GetObject() == nullptr);
623 return Result;
624 }
625
627 {
628 int32 Result = NumElements + Count - 1;
630 check(Result == (NumElements + Count - 1));
631 NumElements += Count;
633 check(Objects[Result].GetObject() == nullptr);
634 return Result;
635 }
636
638 {
639 check(Index >= 0 && Index < NumElements);
640 return &Objects[Index];
641 }
642
644 {
645 check(Index >= 0 && Index < NumElements);
646 return &Objects[Index];
647 }
648
655 {
656 return NumElements;
657 }
658
665 {
666 return MaxElements;
667 }
668
676 {
677 return Index < Num() && Index >= 0;
678 }
685 inline FUObjectItem const& operator[](int32 Index) const
686 {
687 FUObjectItem const* ItemPtr = GetObjectPtr(Index);
688 check(ItemPtr);
689 return *ItemPtr;
690 }
691
693 {
694 FUObjectItem* ItemPtr = GetObjectPtr(Index);
695 check(ItemPtr);
696 return *ItemPtr;
697 }
698
703 {
704 return nullptr;
705 }
706};
707
716{
717 enum
718 {
719 NumElementsPerChunk = 64 * 1024,
720 };
721
723 FUObjectItem** Objects;
725 FUObjectItem* PreAllocatedObjects;
727 TSAN_ATOMIC(int32) MaxElements;
729 TSAN_ATOMIC(int32) NumElements;
731 int32 MaxChunks;
733 TSAN_ATOMIC(int32) NumChunks;
734
735 static constexpr bool bFUObjectItemIsPacked = UE_ENABLE_FUOBJECT_ITEM_PACKING;
736
737
741 void ExpandChunksToIndex(int32 Index)
742 {
743 check(Index >= 0 && Index < MaxElements);
744 int32 ChunkIndex = Index / NumElementsPerChunk;
745 while (ChunkIndex >= NumChunks)
746 {
747 // add a chunk, and make sure nobody else tries
748 FUObjectItem** Chunk = &Objects[NumChunks];
749 FUObjectItem* NewChunk = new FUObjectItem[NumElementsPerChunk];
750 if (FPlatformAtomics::InterlockedCompareExchangePointer((void**)Chunk, NewChunk, nullptr))
751 {
752 // someone else beat us to the add, we don't support multiple concurrent adds
753 check(0);
754 }
755 else
756 {
757 NumChunks++;
758 check(NumChunks <= MaxChunks);
759 }
760 }
761 check(ChunkIndex < NumChunks && Objects[ChunkIndex]); // should have a valid pointer now
762 }
763
764public:
765
768 : Objects(nullptr)
769 , PreAllocatedObjects(nullptr)
770 , MaxElements(0)
771 , NumElements(0)
772 , MaxChunks(0)
773 , NumChunks(0)
774 {
775 }
776
778 {
779 if (!PreAllocatedObjects)
780 {
781 for (int32 ChunkIndex = 0; ChunkIndex < MaxChunks; ++ChunkIndex)
782 {
783 delete[] Objects[ChunkIndex];
784 }
785 }
786 else
787 {
788 delete[] PreAllocatedObjects;
789 }
790 delete[] Objects;
791 }
792
798 {
799 check(!Objects);
800 MaxChunks = InMaxElements / NumElementsPerChunk + 1;
801 MaxElements = MaxChunks * NumElementsPerChunk;
802 Objects = new FUObjectItem*[MaxChunks];
803 FMemory::Memzero(Objects, sizeof(FUObjectItem*) * MaxChunks);
805 {
806 // Fully allocate all chunks as contiguous memory
807 PreAllocatedObjects = new FUObjectItem[MaxElements];
808 for (int32 ChunkIndex = 0; ChunkIndex < MaxChunks; ++ChunkIndex)
809 {
810 Objects[ChunkIndex] = PreAllocatedObjects + ChunkIndex * NumElementsPerChunk;
811 }
812 NumChunks = MaxChunks;
813 }
814 }
815
822 {
823 return NumElements;
824 }
825
832 {
833 return MaxElements;
834 }
835
843 {
844 return Index < Num() && Index >= 0;
845 }
846
852 {
853 const uint32 ChunkIndex = (uint32)Index / NumElementsPerChunk;
854 const uint32 WithinChunkIndex = (uint32)Index % NumElementsPerChunk;
855 checkf(IsValidIndex(Index), TEXT("IsValidIndex(%d)"), Index);
856 checkf(ChunkIndex < (uint32)NumChunks, TEXT("ChunkIndex (%d) < NumChunks (%d)"), ChunkIndex, (int32)NumChunks);
857 checkf(Index < MaxElements, TEXT("Index (%d) < MaxElements (%d)"), Index, (int32)MaxElements);
858 FUObjectItem* Chunk = Objects[ChunkIndex];
859 check(Chunk);
860 return Chunk + WithinChunkIndex;
861 }
863 {
864 const uint32 ChunkIndex = (uint32)Index / NumElementsPerChunk;
865 const uint32 WithinChunkIndex = (uint32)Index % NumElementsPerChunk;
866 checkf(IsValidIndex(Index), TEXT("IsValidIndex(%d)"), Index);
867 checkf(ChunkIndex < (uint32)NumChunks, TEXT("ChunkIndex (%d) < NumChunks (%d)"), ChunkIndex, (int32)NumChunks);
868 checkf(Index < MaxElements, TEXT("Index (%d) < MaxElements (%d)"), Index, (int32)MaxElements);
869 FUObjectItem* Chunk = Objects[ChunkIndex];
870 check(Chunk);
871 return Chunk + WithinChunkIndex;
872 }
873
874 inline void PrefetchObjectPtr(int32 Index) const
875 {
876 const uint32 ChunkIndex = (uint32)Index / NumElementsPerChunk;
877 const uint32 WithinChunkIndex = (uint32)Index % NumElementsPerChunk;
878 const FUObjectItem* Chunk = Objects[ChunkIndex];
880 }
881
888 inline FUObjectItem const& operator[](int32 Index) const
889 {
890 FUObjectItem const* ItemPtr = GetObjectPtr(Index);
891 check(ItemPtr);
892 return *ItemPtr;
893 }
895 {
896 FUObjectItem* ItemPtr = GetObjectPtr(Index);
897 check(ItemPtr);
898 return *ItemPtr;
899 }
900
902 {
903 int32 Result = NumElements;
905 ExpandChunksToIndex(Result + NumToAdd - 1);
906 NumElements += NumToAdd;
907 return Result;
908 }
909
911 {
912 return AddRange(1);
913 }
914
919 {
920 return nullptr;
921 }
922
924 {
925 return MaxChunks * sizeof(FUObjectItem*) + NumChunks * NumElementsPerChunk * sizeof(FUObjectItem);
926 }
927};
928
929/***
930*
931* FUObjectArray replaces the functionality of GObjObjects and UObject::Index
932*
933* Note the layout of this data structure is mostly to emulate the old behavior and minimize code rework during code restructure.
934* Better data structures could be used in the future, for example maybe all that is needed is a TSet<UObject *>
935* One has to be a little careful with this, especially with the GC optimization. I have seen spots that assume
936* that non-GC objects come before GC ones during iteration.
937*
938**/
940{
941 friend class UObject;
943
944private:
950 COREUOBJECT_API void ResetSerialNumber(UObjectBase* Object);
951
952public:
953
958
963 {
964 public:
972 virtual void NotifyUObjectCreated(const class UObjectBase *Object, int32 Index)=0;
973
977 virtual void OnUObjectArrayShutdown()=0;
978 };
979
984 {
985 public:
987
994 virtual void NotifyUObjectDeleted(const class UObjectBase *Object, int32 Index)=0;
995
999 virtual void OnUObjectArrayShutdown() = 0;
1000
1004 virtual SIZE_T GetAllocatedSize() const
1005 {
1006 return 0;
1007 }
1008 };
1009
1014
1021 COREUOBJECT_API void AllocateObjectPool(int32 MaxUObjects, int32 MaxObjectsNotConsideredByGC, bool bPreAllocateObjectArray);
1022
1028
1033
1038
1041 {
1042 return OpenForDisregardForGC;
1043 }
1044
1051 {
1052 return MaxObjectsNotConsideredByGC > 0;
1053 }
1054
1064
1071
1079 {
1080 return Object->InternalIndex;
1081 }
1082
1090 {
1091 check(Index >= 0);
1092 if (Index < ObjObjects.Num())
1093 {
1094 return const_cast<FUObjectItem*>(&ObjObjects[Index]);
1095 }
1096 return nullptr;
1097 }
1098
1100 {
1101 return const_cast<FUObjectItem*>(&ObjObjects[Index]);
1102 }
1103
1105 {
1106 FUObjectItem* ObjectItem = IndexToObject(Index);
1107 if (ObjectItem && ObjectItem->GetObject())
1108 {
1110 {
1111 ObjectItem = nullptr;
1112 }
1113 }
1114 return ObjectItem;
1115 }
1116
1118 {
1119 FUObjectItem* ObjectItem = IndexToObject(Object->InternalIndex);
1120 return ObjectItem;
1121 }
1122
1123 inline bool IsValid(FUObjectItem* ObjectItem, bool bEvenIfGarbage)
1124 {
1125 if (ObjectItem)
1126 {
1128 }
1129 return false;
1130 }
1131
1133 {
1134 FUObjectItem* ObjectItem = IndexToObject(Index);
1135 return IsValid(ObjectItem, bEvenIfGarbage) ? ObjectItem : nullptr;
1136 }
1137
1139 {
1140 // This method assumes Index points to a valid object.
1141 FUObjectItem* ObjectItem = IndexToObject(Index);
1142 return IsValid(ObjectItem, bEvenIfGarbage);
1143 }
1144
1146 {
1147 // This method assumes ObjectItem is valid.
1149 }
1150
1152 {
1153 // This method assumes Index points to a valid object.
1154 FUObjectItem* ObjectItem = IndexToObject(Index);
1155 if (ObjectItem)
1156 {
1157 return IsStale(ObjectItem, bIncludingGarbage);
1158 }
1159 return true;
1160 }
1161
1164 {
1165 return ObjFirstGCIndex;
1166 }
1167
1173 COREUOBJECT_API void AddUObjectCreateListener(FUObjectCreateListener* Listener);
1174
1180 COREUOBJECT_API void RemoveUObjectCreateListener(FUObjectCreateListener* Listener);
1181
1187 COREUOBJECT_API void AddUObjectDeleteListener(FUObjectDeleteListener* Listener);
1188
1194 COREUOBJECT_API void RemoveUObjectDeleteListener(FUObjectDeleteListener* Listener);
1195
1202
1209 COREUOBJECT_API bool IsValid(const UObjectBase* Object) const;
1210
1213 {
1214 return ObjObjects.IsValidIndex(Object->InternalIndex);
1215 }
1216
1224 {
1225 return ObjectIndex <= ObjLastNonGCIndex;
1226 }
1227
1235 {
1236 return IsIndexDisregardForGC(Object->InternalIndex);
1237 }
1244 {
1245 return ObjObjects.Num();
1246 }
1247
1254 {
1255 return ObjObjects.Num() - (ObjLastNonGCIndex + 1);
1256 }
1257
1264 {
1265 return ObjLastNonGCIndex + 1;
1266 }
1267
1275 {
1276 return ObjObjects.Num() - ObjAvailableListEstimateCount;
1277 }
1278
1283 {
1284 return ObjObjects.Capacity() - GetObjectArrayNumMinusAvailable();
1285 }
1286
1291 {
1292 return ObjObjects.Capacity();
1293 }
1294
1299
1306
1313 {
1314 FUObjectItem* ObjectItem = IndexToObject(Index);
1315 checkSlow(ObjectItem);
1316 return ObjectItem->GetSerialNumber();
1317 }
1318
1319#if UE_WITH_REMOTE_OBJECT_HANDLE
1320
1326 inline FRemoteObjectId GetRemoteId(int32 Index)
1327 {
1328 FUObjectItem* ObjectItem = IndexToObject(Index);
1329 checkSlow(ObjectItem);
1330 return ObjectItem->GetRemoteId();
1331 }
1332#endif
1333
1336 {
1337#if THREADSAFE_UOBJECTS
1338 ObjObjectsCritical.Lock();
1339#else
1341#endif
1342 }
1343
1346 {
1347#if THREADSAFE_UOBJECTS
1348 ObjObjectsCritical.Unlock();
1349#endif
1350 }
1351
1356 {
1357 public:
1359 {
1360 EndTag
1362
1370 Array(InArray),
1371 Index(-1),
1372 CurrentObject(nullptr)
1373 {
1374 if (bOnlyGCedObjects)
1375 {
1376 Index = Array.ObjLastNonGCIndex;
1377 }
1378 Advance();
1379 }
1380
1388 Array (InIter.Array),
1389 Index(Array.ObjObjects.Num())
1390 {
1391 }
1392
1397 {
1398 Advance();
1399 }
1400
1401 bool operator==(const TIterator& Rhs) const { return Index == Rhs.Index; }
1402 bool operator!=(const TIterator& Rhs) const { return Index != Rhs.Index; }
1403
1405 UE_FORCEINLINE_HINT explicit operator bool() const
1406 {
1407 return !!CurrentObject;
1408 }
1411 {
1412 return !(bool)*this;
1413 }
1414
1416 {
1417 return Index;
1418 }
1419
1420 protected:
1421
1428 {
1429 return CurrentObject;
1430 }
1435 inline bool Advance()
1436 {
1437 //@todo UE check this for LHS on Index on consoles
1438 FUObjectItem* NextObject = nullptr;
1439 CurrentObject = nullptr;
1440 while(++Index < Array.GetObjectArrayNum())
1441 {
1442 NextObject = const_cast<FUObjectItem*>(&Array.ObjObjects[Index]);
1443 if (NextObject->GetObject())
1444 {
1445 CurrentObject = NextObject;
1446 return true;
1447 }
1448 }
1449 return false;
1450 }
1451
1454 {
1455 return Array;
1456 }
1457
1458 private:
1460 const FUObjectArray& Array;
1462 int32 Index;
1464 mutable FUObjectItem* CurrentObject;
1465 };
1466
1469 {
1470#if THREADSAFE_UOBJECTS
1472#endif
1473 }
1474
1477 {
1478#if THREADSAFE_UOBJECTS
1480#endif
1481 }
1482
1483private:
1484
1485 //typedef TStaticIndirectArrayThreadSafeRead<UObjectBase, 8 * 1024 * 1024 /* Max 8M UObjects */, 16384 /* allocated in 64K/128K chunks */ > TUObjectArray;
1486 typedef FChunkedFixedUObjectArray TUObjectArray;
1487
1488 // note these variables are left with the Obj prefix so they can be related to the historical GObj versions
1489
1491 int32 ObjFirstGCIndex;
1493 int32 ObjLastNonGCIndex;
1495 int32 MaxObjectsNotConsideredByGC;
1496
1498 bool OpenForDisregardForGC;
1500 TUObjectArray ObjObjects;
1502 mutable FTransactionallySafeCriticalSection ObjObjectsCritical;
1504 TArray<int32> ObjAvailableList;
1507
1511 TArray<FUObjectCreateListener* > UObjectCreateListeners;
1515 TArray<FUObjectDeleteListener* > UObjectDeleteListeners;
1516#if THREADSAFE_UOBJECTS
1518#endif
1519
1521 FThreadSafeCounter PrimarySerialNumber;
1522
1524 bool bShouldRecycleObjectIndices = true;
1525
1526public:
1527
1530 {
1531 return ObjObjects;
1532 }
1533
1535 {
1536 return ObjObjects;
1537 }
1538
1540 {
1541 UE::TScopeLock ObjListLock(ObjObjectsCritical);
1542#if THREADSAFE_UOBJECTS
1544#endif
1545 return ObjObjects.GetAllocatedSize() + ObjAvailableList.GetAllocatedSize() + UObjectCreateListeners.GetAllocatedSize() + UObjectDeleteListeners.GetAllocatedSize();
1546 }
1547
1549 {
1550#if THREADSAFE_UOBJECTS
1552#endif
1553 SIZE_T AllocatedSize = 0;
1554 for (FUObjectDeleteListener* Listener : UObjectDeleteListeners)
1555 {
1556 AllocatedSize += Listener->GetAllocatedSize();
1557 }
1558 if (OutNumListeners)
1559 {
1560 *OutNumListeners = UObjectDeleteListeners.Num();
1561 }
1562 return AllocatedSize;
1563 }
1564
1566};
1567
1594
1596{
1598 TArray<FUObjectCluster> Clusters;
1600 TArray<int32> FreeClusterIndices;
1602 int32 NumAllocatedClusters;
1604 bool bClustersNeedDissolving;
1605
1607 COREUOBJECT_API void DissolveCluster(FUObjectCluster& Cluster);
1608
1609public:
1610
1612
1614 {
1615 checkf(Index >= 0 && Index < Clusters.Num(), TEXT("Cluster index %d out of range [0, %d]"), Index, Clusters.Num());
1616 return Clusters[Index];
1617 }
1618
1621
1624
1630
1631
1637
1643
1646
1647 /*** Returns the minimum cluster size as specified in ini settings */
1649
1652 {
1653 return Clusters;
1654 }
1655
1658 {
1659 return NumAllocatedClusters;
1660 }
1661
1664 {
1665 bClustersNeedDissolving = true;
1666 }
1667
1670 {
1671 return bClustersNeedDissolving;
1672 }
1673};
1674
1678
1683{
1685 {
1687 return ObjectItem ? ObjectItem->GetObject() : nullptr;
1688 }
1689};
1690
1691namespace verse
1692{
1694}
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define TSAN_ATOMIC(Type)
Definition CoreMiscDefines.h:147
#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::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:12
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:8
@ Num
Definition MetalRHIPrivate.h:234
const bool
Definition NetworkReplayStreaming.h:178
#define EInternalObjectFlags_AllFlags
Definition ObjectMacros.h:678
#define EInternalObjectFlags_RootFlags
Definition ObjectMacros.h:679
EInternalObjectFlags
Definition ObjectMacros.h:631
@ Unreachable
Object is not reachable on the object graph.
@ Garbage
Garbage from logical point of view and should not be referenced. This flag is mirrored in EObjectFlag...
@ RootSet
Object will not be garbage collected, even if unreferenced.
EObjectFlags
Definition ObjectMacros.h:552
#define EInternalObjectFlags_MinFlagBitIndex
Definition ObjectMacros.h:675
#define EInternalObjectFlags_RefCountMask
Definition ObjectMacros.h:676
WIDECHAR PROFILER_CHAR
Definition StatsCommon.h:24
CORE_API bool IsInGameThread()
Definition ThreadingBase.cpp:185
::FCriticalSection FTransactionallySafeCriticalSection
Definition TransactionallySafeCriticalSection.h:16
#define UE_ENABLE_FUOBJECT_ITEM_PACKING
Definition UObjectArray.h:25
COREUOBJECT_API FUObjectClusterContainer GUObjectClusters
Definition UObjectArray.cpp:27
COREUOBJECT_API FUObjectArray GUObjectArray
Definition UObjectHash.cpp:55
if(Failed) console_printf("Failed.\n")
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition UObjectArray.h:716
UE_FORCEINLINE_HINT int32 Num() const
Definition UObjectArray.h:821
~FChunkedFixedUObjectArray()
Definition UObjectArray.h:777
void PreAllocate(int32 InMaxElements, bool bPreAllocateChunks)
Definition UObjectArray.h:797
UE_FORCEINLINE_HINT int32 Capacity() const
Definition UObjectArray.h:831
int64 GetAllocatedSize() const
Definition UObjectArray.h:923
FChunkedFixedUObjectArray()
Definition UObjectArray.h:767
int32 AddSingle()
Definition UObjectArray.h:910
FUObjectItem *** GetRootBlockForDebuggerVisualizers()
Definition UObjectArray.h:918
UE_FORCEINLINE_HINT bool IsValidIndex(int32 Index) const
Definition UObjectArray.h:842
int32 AddRange(int32 NumToAdd)
Definition UObjectArray.h:901
FUObjectItem & operator[](int32 Index)
Definition UObjectArray.h:894
void PrefetchObjectPtr(int32 Index) const
Definition UObjectArray.h:874
FUObjectItem * GetObjectPtr(int32 Index)
Definition UObjectArray.h:862
FUObjectItem const * GetObjectPtr(int32 Index) const
Definition UObjectArray.h:851
FUObjectItem const & operator[](int32 Index) const
Definition UObjectArray.h:888
Definition UObjectArray.h:582
UE_FORCEINLINE_HINT int32 Num() const
Definition UObjectArray.h:654
int32 AddRange(int32 Count)
Definition UObjectArray.h:626
~FFixedUObjectArray()
Definition UObjectArray.h:599
int32 AddSingle()
Definition UObjectArray.h:615
UObjectBase *** GetRootBlockForDebuggerVisualizers()
Definition UObjectArray.h:702
FFixedUObjectArray()
Definition UObjectArray.h:592
FUObjectItem const & operator[](int32 Index) const
Definition UObjectArray.h:685
FUObjectItem & operator[](int32 Index)
Definition UObjectArray.h:692
void PreAllocate(int32 InMaxElements)
Definition UObjectArray.h:608
FUObjectItem * GetObjectPtr(int32 Index)
Definition UObjectArray.h:643
UE_FORCEINLINE_HINT bool IsValidIndex(int32 Index) const
Definition UObjectArray.h:675
UE_FORCEINLINE_HINT int32 Capacity() const
Definition UObjectArray.h:664
FUObjectItem const * GetObjectPtr(int32 Index) const
Definition UObjectArray.h:637
Definition UObjectGlobals.cpp:3494
Definition NameTypes.h:617
Definition ThreadSafeCounter.h:14
Definition UObjectArray.h:963
virtual void NotifyUObjectCreated(const class UObjectBase *Object, int32 Index)=0
virtual ~FUObjectCreateListener()
Definition UObjectArray.h:965
Definition UObjectArray.h:984
virtual SIZE_T GetAllocatedSize() const
Definition UObjectArray.h:1004
virtual void NotifyUObjectDeleted(const class UObjectBase *Object, int32 Index)=0
virtual ~FUObjectDeleteListener()
Definition UObjectArray.h:986
Definition UObjectArray.h:1356
TIterator(EEndTagType, const TIterator &InIter)
Definition UObjectArray.h:1387
bool Advance()
Definition UObjectArray.h:1435
bool operator!=(const TIterator &Rhs) const
Definition UObjectArray.h:1402
bool operator==(const TIterator &Rhs) const
Definition UObjectArray.h:1401
TIterator(const FUObjectArray &InArray, bool bOnlyGCedObjects=false)
Definition UObjectArray.h:1369
const FUObjectArray & GetIteratedArray() const
Definition UObjectArray.h:1453
EEndTagType
Definition UObjectArray.h:1359
@ EndTag
Definition UObjectArray.h:1360
UE_FORCEINLINE_HINT bool operator!() const
Definition UObjectArray.h:1410
UE_FORCEINLINE_HINT void operator++()
Definition UObjectArray.h:1396
UE_FORCEINLINE_HINT FUObjectItem * GetObject() const
Definition UObjectArray.h:1427
UE_FORCEINLINE_HINT int32 GetIndex() const
Definition UObjectArray.h:1415
Definition UObjectArray.h:940
bool IsValid(int32 Index, bool bEvenIfGarbage)
Definition UObjectArray.h:1138
UE_FORCEINLINE_HINT int32 GetObjectArrayNumMinusPermanent() const
Definition UObjectArray.h:1253
void LockInternalArray() const
Definition UObjectArray.h:1335
COREUOBJECT_API FUObjectArray()
Definition UObjectArray.cpp:106
UE_FORCEINLINE_HINT bool IsIndexDisregardForGC(int32 ObjectIndex) const
Definition UObjectArray.h:1223
int32 GetObjectArrayEstimatedAvailable() const
Definition UObjectArray.h:1282
COREUOBJECT_API void OpenDisregardForGC()
Definition UObjectArray.cpp:138
FUObjectItem * IndexToObject(int32 Index, bool bEvenIfGarbage)
Definition UObjectArray.h:1104
bool IsOpenForDisregardForGC() const
Definition UObjectArray.h:1040
COREUOBJECT_API void AllocateUObjectIndex(class UObjectBase *Object, EInternalObjectFlags InitialFlags, int32 AlreadyAllocatedIndex=-1, int32 SerialNumber=0, FRemoteObjectId RemoteId=FRemoteObjectId())
Definition UObjectArray.cpp:230
UE_FORCEINLINE_HINT bool IsDisregardForGC(const class UObjectBase *Object) const
Definition UObjectArray.h:1234
COREUOBJECT_API void DumpUObjectCountsToLog() const
Definition UObjectArray.cpp:571
COREUOBJECT_API void ShutdownUObjectArray()
Definition UObjectArray.cpp:548
SIZE_T GetAllocatedSize() const
Definition UObjectArray.h:1539
int32 GetObjectArrayNumMinusAvailable() const
Definition UObjectArray.h:1274
FUObjectItem * IndexToObject(int32 Index)
Definition UObjectArray.h:1089
UE_FORCEINLINE_HINT bool IsStale(FUObjectItem *ObjectItem, bool bIncludingGarbage)
Definition UObjectArray.h:1145
bool IsStale(int32 Index, bool bIncludingGarbage)
Definition UObjectArray.h:1151
bool DisregardForGCEnabled() const
Definition UObjectArray.h:1050
UE_FORCEINLINE_HINT int32 GetFirstGCIndex() const
Definition UObjectArray.h:1163
SIZE_T GetDeleteListenersAllocatedSize(int32 *OutNumListeners=nullptr) const
Definition UObjectArray.h:1548
UE_FORCEINLINE_HINT int32 ObjectToIndex(const class UObjectBase *Object) const
Definition UObjectArray.h:1078
COREUOBJECT_API int32 AllocateSerialNumber(int32 Index)
Definition UObjectArray.cpp:515
COREUOBJECT_API void AddUObjectCreateListener(FUObjectCreateListener *Listener)
Definition UObjectArray.cpp:436
int32 GetObjectArrayCapacity() const
Definition UObjectArray.h:1290
void UnlockInternalArray() const
Definition UObjectArray.h:1345
ESerialNumberConstants
Definition UObjectArray.h:955
@ START_SERIAL_NUMBER
Definition UObjectArray.h:956
bool IsValid(FUObjectItem *ObjectItem, bool bEvenIfGarbage)
Definition UObjectArray.h:1123
UE_FORCEINLINE_HINT FUObjectItem * IndexToObjectUnsafeForGC(int32 Index)
Definition UObjectArray.h:1099
COREUOBJECT_API void AddUObjectDeleteListener(FUObjectDeleteListener *Listener)
Definition UObjectArray.cpp:458
COREUOBJECT_API void AllocateObjectPool(int32 MaxUObjects, int32 MaxObjectsNotConsideredByGC, bool bPreAllocateObjectArray)
Definition UObjectArray.cpp:116
COREUOBJECT_API void RemoveObjectFromDeleteListeners(UObjectBase *Object)
Definition UObjectArray.cpp:359
COREUOBJECT_API void RemoveUObjectDeleteListener(FUObjectDeleteListener *Listener)
Definition UObjectArray.cpp:472
const TUObjectArray & GetObjectItemArrayUnsafe() const
Definition UObjectArray.h:1534
COREUOBJECT_API void DisableDisregardForGC()
Definition UObjectArray.cpp:206
void UnlockUObjectDeleteListeners()
Definition UObjectArray.h:1476
void LockUObjectDeleteListeners()
Definition UObjectArray.h:1468
UE_FORCEINLINE_HINT int32 GetObjectArrayNumPermanent() const
Definition UObjectArray.h:1263
FUObjectItem * IndexToValidObject(int32 Index, bool bEvenIfGarbage)
Definition UObjectArray.h:1132
int32 GetSerialNumber(int32 Index)
Definition UObjectArray.h:1312
UE_FORCEINLINE_HINT bool IsValidIndex(const UObjectBase *Object) const
Definition UObjectArray.h:1212
friend COREUOBJECT_API UObject * StaticAllocateObject(const UClass *, UObject *, FName, EObjectFlags, EInternalObjectFlags, bool, bool *, UPackage *, int32, FRemoteObjectId, class FGCReconstructionGuard *)
Definition UObjectGlobals.cpp:3576
COREUOBJECT_API void CloseDisregardForGC()
Definition UObjectArray.cpp:146
TUObjectArray & GetObjectItemArrayUnsafe()
Definition UObjectArray.h:1529
COREUOBJECT_API void RemoveUObjectCreateListener(FUObjectCreateListener *Listener)
Definition UObjectArray.cpp:447
FUObjectItem * ObjectToObjectItem(const UObjectBase *Object)
Definition UObjectArray.h:1117
UE_FORCEINLINE_HINT int32 GetObjectArrayNum() const
Definition UObjectArray.h:1243
COREUOBJECT_API void FreeUObjectIndex(class UObjectBase *Object)
Definition UObjectArray.cpp:378
Definition UObjectArray.h:1596
COREUOBJECT_API int32 AllocateCluster(int32 InRootObjectIndex)
Definition UObjectClusters.cpp:58
COREUOBJECT_API void DissolveClusterAndMarkObjectsAsUnreachable(FUObjectItem *RootObjectItem)
Definition UObjectClusters.cpp:181
FUObjectCluster & operator[](int32 Index)
Definition UObjectArray.h:1613
bool ClustersNeedDissolving() const
Definition UObjectArray.h:1669
TArray< FUObjectCluster > & GetClustersUnsafe()
Definition UObjectArray.h:1651
COREUOBJECT_API FUObjectClusterContainer()
Definition UObjectClusters.cpp:51
COREUOBJECT_API void FreeCluster(int32 InClusterIndex)
Definition UObjectClusters.cpp:76
int32 GetNumAllocatedClusters() const
Definition UObjectArray.h:1657
COREUOBJECT_API FUObjectCluster * GetObjectCluster(UObjectBaseUtility *ClusterRootOrObjectFromCluster)
Definition UObjectClusters.cpp:112
COREUOBJECT_API int32 GetMinClusterSize() const
Definition UObjectClusters.cpp:232
COREUOBJECT_API void DissolveClusters(bool bForceDissolveAllClusters=false)
Definition UObjectClusters.cpp:220
void SetClustersNeedDissolving()
Definition UObjectArray.h:1663
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize(void) const
Definition Array.h:1059
Definition Class.h:3793
Definition GarbageCollectionInternalFlags.h:25
Definition ScopeLock.h:21
Definition UObjectBaseUtility.h:45
Definition UObjectBase.h:59
COREUOBJECT_API void MarkAsReachable() const
Definition GarbageCollection.cpp:6481
Definition Object.h:95
Definition Package.h:216
int
Definition TestServer.py:515
Definition GarbageCollection.cpp:624
bool GIsIncrementalReachabilityPending
Definition GarbageCollection.cpp:620
Definition UObjectArray.h:565
void CheckUObjectLimitReached(const int32 NumUObjects, const int32 MaxUObjects, const int32 NewUObjectCount)
Definition UObjectArray.h:568
COREUOBJECT_API void FailMaxUObjectCountExceeded(const int32 MaxUObjects, const int32 NewUObjectCount)
Definition UObjectArray.cpp:656
Definition Archive.h:36
Definition VVMContentScope.cpp:14
COREUOBJECT_API bool CanAllocateUObjects()
Definition UObjectArray.cpp:665
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
static UE_FORCEINLINE_HINT void MemoryBarrier()
Definition AndroidPlatformMisc.h:249
static FORCEINLINE void Prefetch(const void *Ptr)
Definition GenericPlatformMisc.h:1443
Definition UObjectArray.h:1683
static class UObjectBase * IndexToObject(int32 Index, bool bEvenIfGarbage)
Definition UObjectArray.h:1684
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131
Definition RemoteObjectTypes.h:212
Definition UObjectArray.h:1570
int32 RootIndex
Definition UObjectArray.h:1577
TArray< int32 > MutableObjects
Definition UObjectArray.h:1583
TArray< int32 > Objects
Definition UObjectArray.h:1579
TArray< int32 > ReferencedClusters
Definition UObjectArray.h:1581
TArray< int32 > ReferencedByClusters
Definition UObjectArray.h:1585
bool bNeedsDissolving
Definition UObjectArray.h:1592
FUObjectCluster()
Definition UObjectArray.h:1571
Definition UObjectArray.h:50
UE_FORCEINLINE_HINT void SetGarbage()
Definition UObjectArray.h:324
void AddRef()
Definition UObjectArray.h:355
UE_FORCEINLINE_HINT void SetRootSet()
Definition UObjectArray.h:337
UE_FORCEINLINE_HINT void ClearFlags(EInternalObjectFlags FlagsToClear)
Definition UObjectArray.h:232
UE_FORCEINLINE_HINT bool IsGarbage() const
Definition UObjectArray.h:332
UE_FORCEINLINE_HINT bool HasAnyFlags(EInternalObjectFlags InFlags) const
Definition UObjectArray.h:309
class UObjectBase * GetObject() const
Definition UObjectArray.h:146
int32 SerialNumber
Definition UObjectArray.h:100
FUObjectItem & operator=(const FUObjectItem &)=delete
uint32 ObjectPtrLow
Definition UObjectArray.h:77
int64 FlagsAndRefCount
Definition UObjectArray.h:63
UE_FORCEINLINE_HINT void SetOwnerIndex(int32 OwnerIndex)
Definition UObjectArray.h:172
UE_FORCEINLINE_HINT int32 GetRefCount() const
Definition UObjectArray.h:350
UE_FORCEINLINE_HINT void SetClusterIndex(int32 ClusterIndex)
Definition UObjectArray.h:183
FUObjectItem(FUObjectItem &&)=delete
void ReleaseRef()
Definition UObjectArray.h:383
bool ThisThreadAtomicallyClearedFlag(EInternalObjectFlags FlagToClear)
Definition UObjectArray.h:242
UE_FORCEINLINE_HINT void SetFlags(EInternalObjectFlags FlagsToSet)
Definition UObjectArray.h:218
EInternalObjectFlags GetFlags() const
Definition UObjectArray.h:223
bool ThisThreadAtomicallySetFlag(EInternalObjectFlags FlagToSet)
Definition UObjectArray.h:278
int32 ClusterRootIndex
Definition UObjectArray.h:102
uint8 RemoteId
Definition UObjectArray.h:66
~FUObjectItem()
Definition UObjectArray.h:129
FUObjectItem()
Definition UObjectArray.h:120
int32 GetClusterIndex() const
Definition UObjectArray.h:189
int32 GetSerialNumber() const
Definition UObjectArray.h:195
FUObjectItem & operator=(FUObjectItem &&)=delete
UE_FORCEINLINE_HINT int32 GetOwnerIndex() const
Definition UObjectArray.h:177
UE_FORCEINLINE_HINT bool HasAllFlags(EInternalObjectFlags InFlags) const
Definition UObjectArray.h:314
void SetObject(class UObjectBase *InObject)
Definition UObjectArray.h:158
UE_FORCEINLINE_HINT bool IsUnreachable() const
Definition UObjectArray.h:319
FUObjectItem(const FUObjectItem &)=delete
UE_FORCEINLINE_HINT void ClearGarbage()
Definition UObjectArray.h:328
UE_FORCEINLINE_HINT void ClearRootSet()
Definition UObjectArray.h:341
UE_FORCEINLINE_HINT bool IsRootSet() const
Definition UObjectArray.h:345
Definition LightweightStats.h:416