180 lines
5.5 KiB
C++
180 lines
5.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
GCObject.h: Abstract base class to allow non-UObject objects reference
|
|
UObject instances with proper handling of them by the
|
|
Garbage Collector.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "UObject/Object.h"
|
|
|
|
class FGCObject;
|
|
|
|
class COREUOBJECT_API FGCObject;
|
|
|
|
/**
|
|
* This nested class is used to provide a UObject interface between non
|
|
* UObject classes and the UObject system. It handles forwarding all
|
|
* calls of AddReferencedObjects() to objects/ classes that register with it.
|
|
*/
|
|
class COREUOBJECT_API UGCObjectReferencer: public UObject
|
|
{
|
|
/**
|
|
* This is the list of objects that are referenced
|
|
*/
|
|
TArray<FGCObject*> ReferencedObjects;
|
|
/** Critical section used when adding and removing objects */
|
|
FCriticalSection ReferencedObjectsCritical;
|
|
/** True if we are currently inside AddReferencedObjects */
|
|
bool bIsAddingReferencedObjects = false;
|
|
/** Currently serializing FGCObject*, only valid if bIsAddingReferencedObjects */
|
|
FGCObject* CurrentlySerializingObject = nullptr;
|
|
|
|
public:
|
|
DECLARE_CASTED_CLASS_INTRINSIC_WITH_API(UGCObjectReferencer, UObject, CLASS_Transient, TEXT("/Script/CoreUObject"), CASTCLASS_None, NO_API);
|
|
|
|
/**
|
|
* Adds an object to the referencer list
|
|
*
|
|
* @param Object The object to add to the list
|
|
*/
|
|
void AddObject(FGCObject* Object);
|
|
|
|
/**
|
|
* Removes an object from the referencer list
|
|
*
|
|
* @param Object The object to remove from the list
|
|
*/
|
|
void RemoveObject(FGCObject* Object);
|
|
|
|
/**
|
|
* Get the name of the first FGCObject that owns this object.
|
|
*
|
|
* @param Object The object that we're looking for.
|
|
* @param OutName the name of the FGCObject that reports this object.
|
|
* @param bOnlyIfAddingReferenced Only try to find the name if we are currently inside AddReferencedObjects
|
|
* @return true if the object was found.
|
|
*/
|
|
bool GetReferencerName(UObject* Object, FString& OutName, bool bOnlyIfAddingReferenced = false) const;
|
|
|
|
/**
|
|
* Forwards this call to all registered objects so they can reference
|
|
* any UObjects they depend upon
|
|
*
|
|
* @param InThis This UGCObjectReferencer object.
|
|
* @param Collector The collector of referenced objects.
|
|
*/
|
|
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
|
|
|
|
/**
|
|
* Destroy function that gets called before the object is freed. This might
|
|
* be as late as from the destructor.
|
|
*/
|
|
virtual void FinishDestroy() override;
|
|
};
|
|
|
|
/**
|
|
* This class provides common registration for garbage collection for
|
|
* non-UObject classes. It is an abstract base class requiring you to implement
|
|
* the AddReferencedObjects() method.
|
|
*/
|
|
class COREUOBJECT_API FGCObject
|
|
{
|
|
bool bReferenceAdded = false;
|
|
|
|
void Init()
|
|
{
|
|
// Some objects can get created after the engine started shutting down (lazy init of singletons etc).
|
|
if (!IsEngineExitRequested())
|
|
{
|
|
StaticInit();
|
|
check(GGCObjectReferencer);
|
|
// Add this instance to the referencer's list
|
|
GGCObjectReferencer->AddObject(this);
|
|
bReferenceAdded = true;
|
|
}
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* The static object referencer object that is shared across all
|
|
* garbage collectible non-UObject objects.
|
|
*/
|
|
static UGCObjectReferencer* GGCObjectReferencer;
|
|
|
|
/**
|
|
* Initializes the global object referencer and adds it to the root set.
|
|
*/
|
|
static void StaticInit(void)
|
|
{
|
|
if (GGCObjectReferencer == NULL)
|
|
{
|
|
GGCObjectReferencer = NewObject<UGCObjectReferencer>();
|
|
GGCObjectReferencer->AddToRoot();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tells the global object that forwards AddReferencedObjects calls on to objects
|
|
* that a new object is requiring AddReferencedObjects call.
|
|
*/
|
|
FGCObject(void)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
/** Copy constructor */
|
|
FGCObject(FGCObject const&)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
/** Move constructor */
|
|
FGCObject(FGCObject&&)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
/**
|
|
* Removes this instance from the global referencer's list
|
|
*/
|
|
virtual ~FGCObject(void)
|
|
{
|
|
// GObjectSerializer will be NULL if this object gets destroyed after the exit purge.
|
|
// We want to make sure we remove any objects that were added to the GGCObjectReferencer during Init when exiting
|
|
if (GGCObjectReferencer && bReferenceAdded)
|
|
{
|
|
// Remove this instance from the referencer's list
|
|
GGCObjectReferencer->RemoveObject(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pure virtual that must be overloaded by the inheriting class. Use this
|
|
* method to serialize any UObjects contained that you wish to keep around.
|
|
*
|
|
* @param Collector The collector of referenced objects.
|
|
*/
|
|
virtual void AddReferencedObjects(FReferenceCollector& Collector) = 0;
|
|
|
|
/**
|
|
* Use this method to report a name for your referencer.
|
|
*/
|
|
virtual FString GetReferencerName() const
|
|
{
|
|
return "Unknown FGCObject";
|
|
}
|
|
|
|
/**
|
|
* Use this method to report how the specified object is referenced, if necessary
|
|
*/
|
|
virtual bool GetReferencerPropertyName(UObject* Object, FString& OutPropertyName) const
|
|
{
|
|
return false;
|
|
}
|
|
};
|