UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DelegateBase.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
8#include "UObject/NameTypes.h"
13
14#if !defined(_WIN32) || defined(_WIN64) || (defined(ALLOW_DELEGATE_INLINE_ALLOCATORS_ON_WIN32) && ALLOW_DELEGATE_INLINE_ALLOCATORS_ON_WIN32)
16 #if !defined(NUM_DELEGATE_INLINE_BYTES) || NUM_DELEGATE_INLINE_BYTES == 0
18 #elif NUM_DELEGATE_INLINE_BYTES < 0 || (NUM_DELEGATE_INLINE_BYTES % 16) != 0
19 #error NUM_DELEGATE_INLINE_BYTES must be a multiple of 16
20 #else
22 #endif
23#else
24 // ... except on Win32, because we can't pass 16-byte aligned types by value, as some delegates are
25 // so we'll just keep it heap-allocated, which are always sufficiently aligned.
28#endif
29
30template <typename UserPolicy>
32
33template <typename UserPolicy>
34class TDelegateBase;
35
37
38#if UE_DELEGATE_CHECK_LIFETIME
39
40// This tracking layer allows us to safely check if the code for virtual calls in IDelegateInstance are safe
41// This code will be called on instances that potentially have their code unloaded!
43{
44public:
46#ifdef UE_MODULE_NAME
47 : ModuleName(UE_MODULE_NAME)
48#else
49 : ModuleName(NAME_None)
50#endif //UE_MODULE_NAME
52 {}
53
58 {
60 }
61
65 FName GetModuleName() const
66 {
67 return ModuleName;
68 }
69
74 {
76 }
77
84 {
85 return BoundFunctionName;
86 }
87
93 CORE_API bool IsValid() const;
94
100 CORE_API bool CheckValid() const;
101
102protected:
103
106};
107
108// Convenience macro to check for lifetime validity as widely as possible
109#define CHECK_DELEGATE_LIFETIME(DelegateInstance) \
110 if (DelegateInstance != nullptr) \
111 { \
112 static_cast<const FTrackedDelegateInstanceExtras*>(DelegateInstance)->CheckValid(); \
113 }
114
115#else
116#define CHECK_DELEGATE_LIFETIME(DelegateInstance)
117#endif // UE_DELEGATE_CHECK_LIFETIME
118
119// not thread-safe version, with automatic race detection in dev builds
121{
122 // To extend delegates, you should implement a policy struct like this and pass it as the second template
123 // argument to TDelegate and TMulticastDelegate. This policy struct containing three classes called:
124 //
125 // FDelegateInstanceExtras:
126 // - Must publicly inherit IDelegateInstance.
127 // - Should contain any extra data and functions injected into a binding (the object which holds and
128 // is able to invoke the binding passed to FMyDelegate::CreateSP, FMyDelegate::CreateLambda etc.).
129 // - This binding is not available through the public API of the delegate, but is accessible to FDelegateExtras.
130 //
131 // FDelegateExtras:
132 // - Must publicly inherit TDelegateBase<FThreadSafetyMode>.
133 // - Should contain any extra data and functions injected into a delegate (the object which holds an
134 // FDelegateInstance-derived object, above).
135 // - Public data members and member functions are accessible directly through the TDelegate object.
136 // - Typically member functions in this class will forward calls to the inner FDelegateInstanceExtras,
137 // by downcasting the result of a call to GetDelegateInstanceProtected().
138 //
139 // FMulticastDelegateExtras:
140 // - Must publicly inherit TMulticastDelegateBase<FYourUserPolicyStruct>.
141 // - Should contain any extra data and functions injected into a multicast delegate (the object which
142 // holds an array of FDelegateExtras-derived objects which is the invocation list).
143 // - Public data members and member functions are accessible directly through the TMulticastDelegate object.
144
145#if UE_DELEGATE_CHECK_LIFETIME
147#else
149#endif // UE_DELEGATE_CHECK_LIFETIME
150
152#if UE_DETECT_DELEGATES_RACE_CONDITIONS
154#else
156#endif
159};
160
161// thread-safe version
163{
164 // see `FDefaultDelegateUserPolicy` for documentation
165
166#if UE_DELEGATE_CHECK_LIFETIME
168#else
170#endif // UE_DELEGATE_CHECK_LIFETIME
171
175};
176
177// not thread-safe version, no race detection. used primarily for deprecated unsafe delegates that must be kept running for backward compatibility
190
196
197template <typename ThreadSafetyMode>
199
200template <typename ThreadSafetyMode>
202
203template <typename ThreadSafetyMode>
205{
207
209
211 : WriteScope(Delegate.GetWriteAccessScope())
212 , Allocation(Delegate)
213 {
214 }
215
216private:
219};
220
224template<typename ThreadSafetyMode>
225class TDelegateBase : public TDelegateAccessHandlerBase<ThreadSafetyMode>, private FDelegateAllocation
226{
227 friend struct TWriteLockedDelegateAllocation<ThreadSafetyMode>;
228
229private:
231
232 template <typename>
234
235 template <typename>
236 friend class TDelegateBase;
237
238 template <class, typename, typename, typename...>
240
241 template <bool, class, ESPMode, typename, typename, typename...>
243
244 template <ESPMode, typename, typename, typename, typename...>
246
247 template <bool, class, typename, typename, typename...>
249
250 template <bool, class, typename, typename, typename...>
252
253 template <typename, typename, typename...>
255
256 template <typename, typename, typename, typename...>
258
259 template <typename, typename, typename, typename...>
261
263
264protected:
265 using typename Super::FReadAccessScope;
266 using Super::GetReadAccessScope;
267 using typename Super::FWriteAccessScope;
268 using Super::GetWriteAccessScope;
269
270 explicit TDelegateBase() = default;
271
272public:
274 {
275 Unbind();
276 }
277
279 {
280 MoveConstruct(MoveTemp(Other));
281 }
282
284 {
285 MoveAssign(MoveTemp(Other));
286 return *this;
287 }
288
289 // support for moving from delegates with different thread-safety mode
290 template<typename OtherThreadSafetyMode>
292 {
293 MoveConstruct(MoveTemp(Other));
294 }
295
299 inline void Unbind()
300 {
301 FWriteAccessScope WriteScope = GetWriteAccessScope();
302
303 UnbindUnchecked();
304 }
305
310 {
311 FReadAccessScope ReadScope = GetReadAccessScope();
312
313 return DelegateAllocator.GetAllocatedSize(DelegateSize, sizeof(FAlignedInlineDelegateType));
314 }
315
316#if USE_DELEGATE_TRYGETBOUNDFUNCTIONNAME
317
327 {
328 FReadAccessScope ReadScope = GetReadAccessScope();
329
331 return DelegateInstance ? DelegateInstance->TryGetBoundFunctionName() : NAME_None;
332 }
333
334#endif
335
341 inline class UObject* GetUObject( ) const
342 {
343 FReadAccessScope ReadScope = GetReadAccessScope();
344
346 return DelegateInstance ? DelegateInstance->GetUObject() : nullptr;
347 }
348
354 inline bool IsBound( ) const
355 {
356 FReadAccessScope ReadScope = GetReadAccessScope();
357
359 return DelegateInstance && DelegateInstance->IsSafeToExecute();
360 }
361
367 inline const void* GetObjectForTimerManager() const
368 {
369 FReadAccessScope ReadScope = GetReadAccessScope();
370
372 return DelegateInstance ? DelegateInstance->GetObjectForTimerManager() : nullptr;
373 }
374
384 {
385 FReadAccessScope ReadScope = GetReadAccessScope();
386
388 return DelegateInstance ? DelegateInstance->GetBoundProgramCounterForTimerManager() : 0;
389 }
390
397 {
398 if (!InUserObject)
399 {
400 return false;
401 }
402
403 FReadAccessScope ReadScope = GetReadAccessScope();
404
406 return DelegateInstance && DelegateInstance->HasSameObject(InUserObject);
407 }
408
415 inline bool IsCompactable() const
416 {
417 FReadAccessScope ReadScope = GetReadAccessScope();
418
420 return !DelegateInstance || DelegateInstance->IsCompactable();
421 }
422
429 {
430 FReadAccessScope ReadScope = GetReadAccessScope();
431
433 return DelegateInstance ? DelegateInstance->GetHandle() : FDelegateHandle{};
434 }
435
436protected:
444 {
445 return DelegateSize ? (IDelegateInstance*)DelegateAllocator.GetAllocation() : nullptr;
446 }
447
449 {
450 return DelegateSize ? (const IDelegateInstance*)DelegateAllocator.GetAllocation() : nullptr;
451 }
452
453private:
454 template<typename OtherThreadSafetyMode>
455 void MoveConstruct(TDelegateBase<OtherThreadSafetyMode>&& Other)
456 {
458
459 DelegateAllocator.MoveToEmpty(Other.DelegateAllocator);
460 DelegateSize = Other.DelegateSize;
461 Other.DelegateSize = 0;
462 }
463
464 template<typename OtherThreadSafetyMode>
466 {
469 {
471 OtherDelegateAllocator.MoveToEmpty(Other.DelegateAllocator);
472 OtherDelegateSize = Other.DelegateSize;
473 Other.DelegateSize = 0;
474 }
475
476 {
477 FWriteAccessScope WriteScope = GetWriteAccessScope();
478
479 UnbindUnchecked();
480 DelegateAllocator.MoveToEmpty(OtherDelegateAllocator);
481 DelegateSize = OtherDelegateSize;
482 }
483 }
484
485private:
486 inline void UnbindUnchecked()
487 {
489 {
490 Ptr->~IDelegateInstance();
491 DelegateAllocator.ResizeAllocation(0, 0, sizeof(FAlignedInlineDelegateType));
492 DelegateSize = 0;
493 }
494 }
495
498};
499
500namespace UE::Core::Private
501{
502 // Should only be called by the TWriteLockedDelegateAllocation<ThreadSafetyMode> overload, because it obtains the write lock
503 CORE_API void* DelegateAllocate(size_t Size, FDelegateAllocation& Allocation);
504}
505
506template <typename ThreadSafetyMode>
508{
509 return UE::Core::Private::DelegateAllocate(Size, LockedAllocation.Allocation);
510}
511
512template <typename ThreadSafetyMode>
TSizedHeapAllocator< 32 > FHeapAllocator
Definition ContainerAllocationPolicies.h:857
#define NUM_DELEGATE_INLINE_BYTES
Definition CoreDefines.h:39
#define UE_NONCOPYABLE(TypeName)
Definition CoreMiscDefines.h:457
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
#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
const void * FDelegateUserObjectConst
Definition IDelegateInstance.h:108
#define ALIAS_TEMPLATE_TYPE_LAYOUT(TemplatePrefix, T, Alias)
Definition MemoryLayout.h:762
const bool
Definition NetworkReplayStreaming.h:178
ESPMode
Definition SharedPointerFwd.h:12
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
Definition IDelegateInstance.h:14
Definition NameTypes.h:617
Definition IDelegateInstance.h:112
Definition DelegateAccessHandler.h:30
Definition DelegateBase.h:226
FDelegateHandle GetHandle() const
Definition DelegateBase.h:428
friend class TBaseFunctorDelegateInstance
Definition DelegateBase.h:257
bool IsBound() const
Definition DelegateBase.h:354
TDelegateBase & operator=(TDelegateBase &&Other)
Definition DelegateBase.h:283
friend class TBaseSPMethodDelegateInstance
Definition DelegateBase.h:242
friend class TBaseUFunctionDelegateInstance
Definition DelegateBase.h:239
bool IsCompactable() const
Definition DelegateBase.h:415
friend class TBaseUObjectMethodDelegateInstance
Definition DelegateBase.h:251
UE_FORCEINLINE_HINT const IDelegateInstance * GetDelegateInstanceProtected() const
Definition DelegateBase.h:448
friend class TBaseStaticDelegateInstance
Definition DelegateBase.h:254
void Unbind()
Definition DelegateBase.h:299
~TDelegateBase()
Definition DelegateBase.h:273
friend class TBaseSPLambdaDelegateInstance
Definition DelegateBase.h:245
UE_FORCEINLINE_HINT IDelegateInstance * GetDelegateInstanceProtected()
Definition DelegateBase.h:443
bool IsBoundToObject(FDelegateUserObjectConst InUserObject) const
Definition DelegateBase.h:396
TDelegateBase(TDelegateBase< OtherThreadSafetyMode > &&Other)
Definition DelegateBase.h:291
uint64 GetBoundProgramCounterForTimerManager() const
Definition DelegateBase.h:383
class UObject * GetUObject() const
Definition DelegateBase.h:341
TDelegateBase()=default
friend class FWriteLockedDelegateAllocation
Definition DelegateBase.h:262
TDelegateBase(TDelegateBase &&Other)
Definition DelegateBase.h:278
friend class TWeakBaseFunctorDelegateInstance
Definition DelegateBase.h:260
const void * GetObjectForTimerManager() const
Definition DelegateBase.h:367
friend class TBaseRawMethodDelegateInstance
Definition DelegateBase.h:248
SIZE_T GetAllocatedSize() const
Definition DelegateBase.h:309
Definition MulticastDelegateBase.h:28
Definition ContainerAllocationPolicies.h:814
Definition ContainerAllocationPolicies.h:618
Definition ContainerAllocationPolicies.h:894
Definition Object.h:95
const FName ModuleName("AssetRegistry")
implementation
Definition PlayInEditorLoadingScope.h:8
FORCEINLINE_DEBUGGABLE void CheckValid(FSchemaView Schema)
Definition GarbageCollection.cpp:1939
Definition DelegateBase.h:121
FNotThreadSafeNotCheckedDelegateMode FThreadSafetyMode
Definition DelegateBase.h:155
Definition DelegateBase.h:163
FThreadSafeDelegateMode FThreadSafetyMode
Definition DelegateBase.h:172
Definition DelegateBase.h:192
FDelegateAllocatorType::ForElementType< FAlignedInlineDelegateType > DelegateAllocator
Definition DelegateBase.h:193
int32 DelegateSize
Definition DelegateBase.h:194
Definition DelegateBase.h:179
FNotThreadSafeNotCheckedDelegateMode FThreadSafetyMode
Definition DelegateBase.h:186
Definition TypeCompatibleBytes.h:17
Definition DelegateBase.h:205
TWriteLockedDelegateAllocation(TDelegateBase< ThreadSafetyMode > &Delegate)
Definition DelegateBase.h:210