October3d55/M/MultiThread/Source/MultiThreadLibrary/Public/ThreadTasksLoop.h

136 lines
3.1 KiB
C++

// Copyright UnexGames 2025. All Rights Reserved.
#pragma once
#include "ThreadBase.h"
#include "ThreadTasks.h"
#include "TimerManager.h"
#include "ThreadTasksLoop.generated.h"
DECLARE_MULTICAST_DELEGATE(FLoopTaskDelegate);
UCLASS(Blueprintable, hidecategories = (Object), meta = (DontUseGenericSpawnObject = "True"))
class MULTITHREADLIBRARY_API UThreadTasksLoop : public UThreadTaskBase
{
friend class FThreadTasksLoopAction;
GENERATED_BODY()
public:
UThreadTasksLoop();
~UThreadTasksLoop();
virtual bool Start() override;
/**
* Called on Background Thread when the Task is executed.
*/
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, meta = (DisplayName = "Task Body"), Category = "MultiThreadLibrary")
void TaskBody(UThreadTasksLoop* WorkerRef);
/**
* Check whether the work is in progress.
*/
virtual bool IsRunning() override;
virtual void TaskBody_Implementation(UThreadTasksLoop* WorkerRef);
virtual void Cancel_Implementation();
public:
int BaseLoopNR;
float BaseLoopInterval;
int RepeatTime = 0;
bool CanLoop = false;
bool bCancel = false;
FLoopTaskDelegate TaskDelegate;
protected:
protected:
int32 CurrentIndex = 0;
bool bStarted = false;
FTimerHandle TickHandle;
};
class MULTITHREADLIBRARY_API FThreadTasksLoopAction : public FTaskActionBase
{
EtaskExecutionBranches& Branches;
bool bStarted;
public:
FThreadTasksLoopAction(UObject* InObject, EtaskExecutionBranches& InBranches, const FLatentActionInfo& LatentInfo, TSubclassOf<class UThreadBase> TaskClass, int BaseLoopNR, float LoopInterval)
: FTaskActionBase(InObject, LatentInfo, TaskClass)
, Branches(InBranches)
, bStarted(false)
{
UThreadTasksLoop* LocalTask = Cast<UThreadTasksLoop>(Task);
if (LocalTask)
{
Branches = EtaskExecutionBranches::OnStart;
LocalTask->BodyFunction();
LocalTask->BaseLoopInterval = LoopInterval;
LocalTask->BaseLoopNR = BaseLoopNR;
LocalTask->TaskDelegate.AddLambda([LocalTask, &InBranches]
{
InBranches = EtaskExecutionBranches::OnTaskBody;
LocalTask->BodyFunction();
});
LocalTask->OnCancelDelegate.AddLambda([LocalTask, &InBranches]
{
InBranches = EtaskExecutionBranches::OnCanceled;
LocalTask->BodyFunction();
});
bStarted = Task->Start();
}
else {
return;
}
}
virtual ~FThreadTasksLoopAction()
{
if (Task != nullptr && Task->IsValidLowLevel() && IsValid(Task) && !Task->IsUnreachable())
{
UThreadTasksLoop* LocalTask = Cast<UThreadTasksLoop>(Task);
if (LocalTask)
{
LocalTask->TaskDelegate.RemoveAll(this);
LocalTask->OnCancelDelegate.RemoveAll(this);
}
}
}
virtual void UpdateOperation(FLatentResponse& Response) override
{
if (bStarted)
{
if (!IsCanceled())
{
if (!IsRunning())
{
Branches = EtaskExecutionBranches::OnCompleted;
Response.FinishAndTriggerIf(true, ExecutionFunction, OutputLink, CallbackTarget);
}
}
else
{
Response.DoneIf(true);
}
}
else {
//If we reached this point it means the task was unable to start.
Branches = EtaskExecutionBranches::OnCompleted;
Response.FinishAndTriggerIf(true, ExecutionFunction, OutputLink, CallbackTarget);
}
}
};