197 lines
4.8 KiB
C++
197 lines
4.8 KiB
C++
// Copyright UnexGames 2025. All Rights Reserved.
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/Object.h"
|
|
#include "UObject/UObjectBaseUtility.h"
|
|
#include "LatentActions.h"
|
|
#include "Engine/LatentActionManager.h"
|
|
#include "Templates/SubclassOf.h"
|
|
#include "UObject/Package.h"
|
|
#include "ThreadUtility.h"
|
|
#include "ThreadBase.generated.h"
|
|
|
|
DECLARE_MULTICAST_DELEGATE(FTaskOnCancelDelegate);
|
|
|
|
UCLASS(HideDropdown, BlueprintType, hidecategories = (Object), meta = (DontUseGenericSpawnObject = "true"))
|
|
class MULTITHREADLIBRARY_API UThreadBase : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UThreadBase();
|
|
~UThreadBase();
|
|
|
|
/**
|
|
* Attempts to start the Task.
|
|
* @return Return False if Task already running.
|
|
*/
|
|
virtual bool Start();
|
|
|
|
/**
|
|
* Attempts to Cancel the Task.
|
|
*/
|
|
virtual void Cancel();
|
|
|
|
/**
|
|
* Check whether the task is in progress.
|
|
*/
|
|
virtual bool IsRunning();
|
|
|
|
/**
|
|
* Check whether the task is canceled.
|
|
*/
|
|
virtual bool IsCanceled();
|
|
|
|
/**
|
|
* Called immediately on Game Thread when the Task is cancelled.
|
|
*/
|
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "On Cancel"), Category = "MultiThreadLibrary")
|
|
void OnCancel();
|
|
virtual void OnCancel_Implementation();
|
|
|
|
|
|
|
|
/**
|
|
* Wait for work work to complete.
|
|
*/
|
|
virtual void WaitToFinish();
|
|
|
|
|
|
|
|
/**
|
|
* Called immediately on Game Thread when the Task is completed.
|
|
*/
|
|
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "On Complete"), Category = "MultiThreadLibrary")
|
|
void OnComplete();
|
|
virtual void OnComplete_Implementation();
|
|
|
|
|
|
|
|
public:
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiThreadLibrary")
|
|
bool bIsTickable = false;
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiThreadLibrary")
|
|
bool bIsTickableInEditor = false;
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MultiThreadLibrary")
|
|
bool bIsTickableWhenPaused = false;
|
|
|
|
FTaskOnCancelDelegate OnCancelDelegate;
|
|
TFunction<void()> BodyFunction;
|
|
protected:
|
|
|
|
virtual UWorld* GetWorld() const override;
|
|
|
|
private:
|
|
|
|
|
|
|
|
protected:
|
|
FThreadSafeBool bCanceled = false;
|
|
|
|
};
|
|
|
|
|
|
UENUM(BlueprintType)
|
|
enum class ETaskResultBranches : uint8
|
|
{
|
|
OnStart,
|
|
OnCompleted,
|
|
OnCanceled,
|
|
};
|
|
|
|
UENUM(BlueprintType)
|
|
enum class EtaskExecutionBranches : uint8
|
|
{
|
|
OnStart,
|
|
OnTaskBody,
|
|
OnCompleted,
|
|
OnCanceled,
|
|
};
|
|
|
|
UENUM(BlueprintType)
|
|
enum class ETaskResultBranchesNoCancel : uint8
|
|
{
|
|
OnStart,
|
|
OnCompleted,
|
|
};
|
|
|
|
UENUM(BlueprintType)
|
|
enum class ETaskResultBranchesNoComplete : uint8
|
|
{
|
|
OnStart,
|
|
OnCanceled,
|
|
};
|
|
|
|
UENUM(BlueprintType)
|
|
enum class ETaskResultBranchesNoCompleteWithBody : uint8
|
|
{
|
|
OnStart,
|
|
OnTaskBody,
|
|
OnCanceled,
|
|
};
|
|
|
|
|
|
class MULTITHREADLIBRARY_API FTaskActionBase : public FPendingLatentAction
|
|
{
|
|
protected:
|
|
UObject* Object;
|
|
FName ExecutionFunction;
|
|
int32 OutputLink;
|
|
FWeakObjectPtr CallbackTarget;
|
|
UThreadBase* Task = nullptr;
|
|
public:
|
|
FTaskActionBase(UObject* InObject, const FLatentActionInfo& LatentInfo, TSubclassOf<class UThreadBase> TaskClass)
|
|
: Object(InObject)
|
|
, ExecutionFunction(LatentInfo.ExecutionFunction)
|
|
, OutputLink(LatentInfo.Linkage)
|
|
, CallbackTarget(LatentInfo.CallbackTarget)
|
|
{
|
|
UThreadUtility::TaskIndex++;
|
|
const FString Name = "Task Work" + FString::FromInt(UThreadUtility::TaskIndex);
|
|
Task = NewObject<UThreadBase>(InObject, TaskClass, FName(*Name), RF_Transient);
|
|
|
|
if (UObject* CallbackObject = CallbackTarget.Get())
|
|
{
|
|
if (UFunction* Function = CallbackObject->FindFunction(ExecutionFunction))
|
|
{
|
|
checkf(CallbackObject && Function, TEXT("Can't find Task Functions."));
|
|
int32 LocalOutputLink = OutputLink;
|
|
Task->BodyFunction = [CallbackObject, Function, LocalOutputLink]()
|
|
{
|
|
int32 FinalOutputLink = LocalOutputLink;
|
|
if (CallbackObject && Function)
|
|
{
|
|
CallbackObject->ProcessEvent(Function, &(FinalOutputLink));
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual ~FTaskActionBase()
|
|
{
|
|
if (Task != nullptr && Task->IsValidLowLevel() && IsValid(Task) && !Task->IsUnreachable())
|
|
{
|
|
Task->Cancel();
|
|
}
|
|
}
|
|
|
|
virtual bool IsRunning()
|
|
{
|
|
if (Task != nullptr && Task->IsValidLowLevel() && IsValid(Task) && !Task->IsUnreachable())
|
|
{
|
|
return Task->IsRunning();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool IsCanceled()
|
|
{
|
|
if (Task != nullptr && Task->IsValidLowLevel() && IsValid(Task) && !Task->IsUnreachable())
|
|
{
|
|
return Task->IsCanceled();
|
|
}
|
|
return true;
|
|
}
|
|
}; |