Dynamic Multicast delegates can now specify that their storage be stored in a sparse allocation for delegates that are expected to be bound rarely. The memory usage of an unbound sparse delegate is 1 byte instead of 16 bytes (for the empty array), however, a bound sparse delegate will have access overhead to retrieve the invocation list from the sparse object annotation.

The definition of the delegate type must specify the class and property name of the delegate that will use it and the type cannot be used outside of that context or just on the stack.
UMulticastDelegateProperty is now abstract and has 2 subclasses (UMulticastDelegateInlineProperty and UMulticastDelegateSparseProperty). The SparseProperty SignatureFunction will be a USparseDelegateFunction.
The sparse delegates do not work correctly with the python bindings at this point, but this will be visited soon.
#rb Michael.Noland
#jira

#ROBOMERGE-OWNER: lina.halper
#ROBOMERGE-AUTHOR: marc.audy
#ROBOMERGE-SOURCE: CL 5295832 via CL 5306530 via CL 5306657
#ROBOMERGE-BOT: ANIM (Main -> Dev-Anim)

[CL 5322213 by marc audy in Dev-Anim branch]
This commit is contained in:
marc audy
2019-03-06 18:02:30 -05:00
parent e5f394829c
commit d5232114b6
28 changed files with 1466 additions and 238 deletions

View File

@@ -953,7 +953,7 @@ FPyConversionResult NativizeProperty_Direct(PyObject* PyObj, const UProperty* Pr
{
EmitPropertyChangeNotifications(InChangeOwner, [&]()
{
CastProp->SetPropertyValue(ValueAddr, *PyDelegate->DelegateInstance);
CastProp->SetMulticastDelegate(ValueAddr, *PyDelegate->DelegateInstance);
});
}
}
@@ -1113,13 +1113,21 @@ FPyConversionResult PythonizeProperty_Direct(const UProperty* Prop, const void*
return FPyConversionResult::Success();
}
if (auto* CastProp = Cast<UMulticastDelegateProperty>(Prop))
if (auto* CastProp = Cast<UMulticastInlineDelegateProperty>(Prop))
{
const FMulticastScriptDelegate* Value = CastProp->GetPropertyValuePtr(ValueAddr);
const FMulticastScriptDelegate* Value = CastProp->GetMulticastDelegate(ValueAddr);
OutPyObj = (PyObject*)FPyWrapperMulticastDelegateFactory::Get().CreateInstance(CastProp->SignatureFunction, (FMulticastScriptDelegate*)Value, OwnerContext, ConversionMethod);
return FPyConversionResult::Success();
}
// TODO: We're just not handling sparse delegates at this time
/*if (auto* CastProp = Cast<UMulticastSparseDelegateProperty>(Prop))
{
const FMulticastScriptDelegate* Value = CastProp->GetMulticastDelegate(ValueAddr);
OutPyObj = (PyObject*)FPyWrapperMulticastDelegateFactory::Get().CreateInstance(CastProp->SignatureFunction, (FMulticastScriptDelegate*)Value, OwnerContext, ConversionMethod);
return FPyConversionResult::Success();
}*/
if (auto* CastProp = Cast<UArrayProperty>(Prop))
{
OutPyObj = (PyObject*)FPyWrapperArrayFactory::Get().CreateInstance((void*)ValueAddr, CastProp, OwnerContext, ConversionMethod);

View File

@@ -78,7 +78,7 @@ void FPyReferenceCollector::AddReferencedObjectsFromDelegate(FReferenceCollector
}
}
void FPyReferenceCollector::AddReferencedObjectsFromMulticastDelegate(FReferenceCollector& InCollector, FMulticastScriptDelegate& InDelegate)
void FPyReferenceCollector::AddReferencedObjectsFromMulticastDelegate(FReferenceCollector& InCollector, const FMulticastScriptDelegate& InDelegate)
{
// Keep the delegate objects alive if they're using a Python proxy instance
// We have to use the EvenIfUnreachable variant here as the objects are speculatively marked as unreachable during GC
@@ -192,8 +192,10 @@ void FPyReferenceCollector::AddReferencedObjectsFromPropertyInternal(FReferenceC
{
for (int32 ArrIndex = 0; ArrIndex < InProp->ArrayDim; ++ArrIndex)
{
FMulticastScriptDelegate* Value = CastProp->GetPropertyValuePtr(CastProp->ContainerPtrToValuePtr<void>(InBaseAddr, ArrIndex));
AddReferencedObjectsFromMulticastDelegate(InCollector, *Value);
if (const FMulticastScriptDelegate* Value = CastProp->GetMulticastDelegate(CastProp->ContainerPtrToValuePtr<void>(InBaseAddr, ArrIndex)))
{
AddReferencedObjectsFromMulticastDelegate(InCollector, *Value);
}
}
}
return;

View File

@@ -51,7 +51,7 @@ public:
static void AddReferencedObjectsFromDelegate(FReferenceCollector& InCollector, FScriptDelegate& InDelegate);
/** Utility function to ARO a multicast delegate instance */
static void AddReferencedObjectsFromMulticastDelegate(FReferenceCollector& InCollector, FMulticastScriptDelegate& InDelegate);
static void AddReferencedObjectsFromMulticastDelegate(FReferenceCollector& InCollector, const FMulticastScriptDelegate& InDelegate);
/** Utility function to ARO all properties on a struct instance */
static void AddReferencedObjectsFromStruct(FReferenceCollector& InCollector, const UStruct* InStruct, void* InStructAddr, const EPyReferenceCollectorFlags InFlags = EPyReferenceCollectorFlags::IncludeAll);