136 lines
3.1 KiB
C++
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);
|
|
}
|
|
}
|
|
}; |