UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DeferredRegistry.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6
7#if !UE_WITH_CONSTINIT_UOBJECT
8
10#include "UObject/Class.h"
11#include "UObject/Reload.h"
12#include "UObject/UObjectBase.h"
13
14#if WITH_RELOAD
16{
17 return lhs.Size != rhs.Size || lhs.Hash != rhs.Hash;
18}
19
21{
22 return lhs.Size != rhs.Size || lhs.Hash != rhs.Hash;
23}
24
26{
27 return lhs.Hash != rhs.Hash;
28}
29
31{
32 return lhs.BodyHash != rhs.BodyHash || lhs.DeclarationsHash != rhs.DeclarationsHash;
33}
34
39#endif
40
41template <typename T>
43{
44public:
45 using TInfo = T;
46 using TType = typename T::TType;
47 using TVersion = typename T::TVersion;
48
49 enum class AddResult
50 {
51 New,
54 };
55
56private:
57
58 using FPackageAndNameKey = TTuple<FName, FName>;
59
60public:
61
66 {
67 TType* (*OuterRegisterFn)();
68 TType* (*InnerRegisterFn)();
70 const TCHAR* Name;
72#if WITH_RELOAD
74#endif
75
76#if WITH_RELOAD
77 bool bHasChanged;
78#endif
79 };
80
81public:
82
93 {
94#if WITH_RELOAD
96 TInfo** ExistingInfo = InfoMap.Find(Key);
97
98 bool bHasChanged = !ExistingInfo || (*ExistingInfo)->ReloadVersionInfo != InVersion;
99 InInfo.ReloadVersionInfo = InVersion;
100 TType* OldSingleton = ExistingInfo ? ((*ExistingInfo)->InnerSingleton ? (*ExistingInfo)->InnerSingleton : (*ExistingInfo)->OuterSingleton) : nullptr;
101
102 bool bAdd = true;
103 if (ExistingInfo)
104 {
106 {
107 bAdd = Reload->GetEnableReinstancing(bHasChanged);
108 }
109 if (bAdd)
110 {
111 if (!bHasChanged)
112 {
113 // With live coding, the existing might be the same as the new info.
114 // We still invoke the copy method to allow UClasses to clear the singletons.
116 }
118 }
119 }
120 else
121 {
122 InfoMap.Add(Key, &InInfo);
123 }
124 if (bAdd)
125 {
126 Registrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, InName, &InInfo, OldSingleton, bHasChanged });
127 }
129#else
130 Registrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, InName, &InInfo });
131 return AddResult::New;
132#endif
133 }
134
138#if WITH_RELOAD
139 TType* FindMatchingObject(const TCHAR* InPackageName, const TCHAR* InName, const TVersion& InVersion)
140 {
141 const FPackageAndNameKey Key = FPackageAndNameKey{ InPackageName, InName };
142 TInfo** ExistingInfo = InfoMap.Find(Key);
143 if (ExistingInfo == nullptr)
144 {
145 return nullptr;
146 }
147 if ((*ExistingInfo)->ReloadVersionInfo != InVersion)
148 {
149 return nullptr;
150 }
151 return (*ExistingInfo)->InnerSingleton;
152 }
153#endif
154
159 {
160 return Registrations;
161 }
162
167 {
168 return ProcessedRegistrations < Registrations.Num();
169 }
170
175 {
176 for (int32 Index = ProcessedRegistrations, Num = Registrations.Num(); Index < Num; ++Index)
177 {
178 CreatePackage(Registrations[Index].PackageName);
179 }
180 }
181
185 void DoPendingInnerRegistrations(bool UpdateCounter)
186 {
187 int32 Num = Registrations.Num();
188 for (int32 Index = ProcessedRegistrations; Index < Num; ++Index)
189 {
190 InnerRegister(Registrations[Index]);
191 }
192
193 if (UpdateCounter)
194 {
195 ProcessedRegistrations = Num;
196 }
197 }
198
202 void DoPendingOuterRegistrations(bool UpdateCounter)
203 {
204 int32 Num = Registrations.Num();
205 for (int32 Index = ProcessedRegistrations; Index < Num; ++Index)
206 {
207 OuterRegister(Registrations[Index]);
208 }
209
210 if (UpdateCounter)
211 {
212 ProcessedRegistrations = Num;
213 }
214 }
215
219 template <typename FuncType>
220 void DoPendingOuterRegistrations(bool UpdateCounter, FuncType&& InOnRegistration)
221 {
222 int32 Num = Registrations.Num();
223 for (int32 Index = ProcessedRegistrations; Index < Num; ++Index)
224 {
225 TType* Object = OuterRegister(Registrations[Index]);
226 InOnRegistration(Registrations[Index].PackageName, *Object);
227 }
228 if (UpdateCounter)
229 {
230 ProcessedRegistrations = Num;
231 }
232 }
233
238 {
239 return Registrant.InnerRegisterFn();
240 }
241
246 {
247 return Registrant.OuterRegisterFn();
248 }
249
254 {
255#if WITH_RELOAD
257 if (Reload != nullptr)
258 {
259 const TCHAR* Prefix = Reload->GetPrefix();
260 for (const FRegistrant& Registrant : Registrations)
261 {
262 if (Registrant.bHasChanged && Registrant.OldSingleton != nullptr)
263 {
264 UE_LOG(LogClass, Log, TEXT("%s %s Reload."), GetRegistryName(), *Registrant.OldSingleton->GetName());
265
266 // Reset the cached class construct info.
267 Registrant.Info->InnerSingleton = nullptr;
268 Registrant.Info->OuterSingleton = nullptr;
269
270 // Perform any other processing needed for existing objects
271 ReloadProcessObject(Registrant.OldSingleton, Prefix);
272
273 // If requested, invoke the registration function to make sure it has been recreated
275 {
276 Registrant.OuterRegisterFn();
277 }
278 }
279 }
280 }
281#endif
282 }
283
287#if WITH_RELOAD
289 {
290 for (const FRegistrant& Registrant : Registrations)
291 {
292 TType* Old = Registrant.OldSingleton;
293 TType* New = Registrant.bHasChanged ? OuterRegister(Registrant) : Old;
294 Reload.NotifyChange(New, Old);
295 }
296 }
297#endif
298
303 {
304 TArray<FRegistrant> Local(MoveTemp(Registrations));
305 ProcessedRegistrations = 0;
306 }
307
312 {
313 NewInfo.InnerSingleton = OldInfo.InnerSingleton;
314 NewInfo.OuterSingleton = OldInfo.OuterSingleton;
315 }
316
321 {
323 return Registry;
324 }
325
326#if WITH_RELOAD
327 const TCHAR* GetRegistryName();
328#endif
329
330private:
331 TArray<FRegistrant> Registrations;
332 int32 ProcessedRegistrations = 0;
333
334#if WITH_RELOAD
336#endif
337};
338
339// Specialization for classes for the LLM_SCOPE
340template <>
348
349// Specialization for class to not copy the existing singletons when reloading a class that hasn't changed.
350// In the case of live coding, we must clear out the pointer for classes to make sure it invokes the registration code.
351template <>
353{
354 NewInfo.InnerSingleton = nullptr;
355 NewInfo.OuterSingleton = nullptr;
356}
357
358#if WITH_RELOAD
359template <> inline const TCHAR* TDeferredRegistry<FClassRegistrationInfo>::GetRegistryName() { return TEXT("UClass"); }
360template <> inline const TCHAR* TDeferredRegistry<FEnumRegistrationInfo>::GetRegistryName() { return TEXT("UEnum"); }
361template <> inline const TCHAR* TDeferredRegistry<FStructRegistrationInfo>::GetRegistryName() { return TEXT("UScriptStruct"); }
362template <> inline const TCHAR* TDeferredRegistry<FPackageRegistrationInfo>::GetRegistryName() { return TEXT("UPackage"); }
363#endif
364
369
370#endif // !UE_WITH_CONSTINIT_UOBJECT
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
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
UE_FORCEINLINE_HINT bool operator!=(const FIndexedPointer &Other) const
Definition LockFreeList.h:76
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
#define LLM_SCOPE_BYTAG(...)
Definition LowLevelMemTracker.h:1099
#define LLM_DEFINE_STATIC_TAG(...)
Definition LowLevelMemTracker.h:1115
#define LLM_SCOPE(...)
Definition LowLevelMemTracker.h:1095
@ Num
Definition MetalRHIPrivate.h:234
IReload * GetActiveReloadInterface()
Definition ModuleManager.h:1175
UPackage * CreatePackage(const TCHAR *PackageName)
Definition UObjectGlobals.cpp:1002
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
Definition Reload.h:19
Definition Array.h:670
Definition DeferredRegistry.h:43
static TDeferredRegistry & Get()
Definition DeferredRegistry.h:320
void DoPendingOuterRegistrations(bool UpdateCounter, FuncType &&InOnRegistration)
Definition DeferredRegistry.h:220
TArray< FRegistrant > & GetRegistrations()
Definition DeferredRegistry.h:158
void ProcessChangedObjects(bool InvokeOuterRegisterFunction=false)
Definition DeferredRegistry.h:253
void UpdateSingletons(TInfo &NewInfo, const TInfo &OldInfo)
Definition DeferredRegistry.h:311
AddResult
Definition DeferredRegistry.h:50
typename T::TVersion TVersion
Definition DeferredRegistry.h:47
void DoPendingPackageRegistrations()
Definition DeferredRegistry.h:174
T TInfo
Definition DeferredRegistry.h:45
typename T::TType TType
Definition DeferredRegistry.h:46
static TType * InnerRegister(const FRegistrant &Registrant)
Definition DeferredRegistry.h:237
void DoPendingOuterRegistrations(bool UpdateCounter)
Definition DeferredRegistry.h:202
void DoPendingInnerRegistrations(bool UpdateCounter)
Definition DeferredRegistry.h:185
bool HasPendingRegistrations()
Definition DeferredRegistry.h:166
AddResult AddRegistration(TType *(*InOuterRegister)(), TType *(*InInnerRegister)(), const TCHAR *InPackageName, const TCHAR *InName, TInfo &InInfo, const TVersion &InVersion)
Adds the given registration information for the given object. Objects are either classes,...
Definition DeferredRegistry.h:92
void EmptyRegistrations()
Definition DeferredRegistry.h:302
static TType * OuterRegister(const FRegistrant &Registrant)
Definition DeferredRegistry.h:245
Definition UnrealString.h.inl:34
Definition Class.h:3793
Definition Class.h:2791
Definition Package.h:216
Definition Class.h:1720
U16 Index
Definition radfft.cpp:71
Definition UObjectBase.h:498
Definition UObjectBase.h:569
Definition UObjectBase.h:605
Definition UObjectBase.h:531
Definition DeferredRegistry.h:66
TInfo * Info
Definition DeferredRegistry.h:71
const TCHAR * PackageName
Definition DeferredRegistry.h:69
const TCHAR * Name
Definition DeferredRegistry.h:70
Definition UObjectBase.h:485
Definition Tuple.h:652