// Copyright UnexGames 2025. All Rights Reserved. #include "ThreadTasksLoop.h" UThreadTasksLoop::UThreadTasksLoop() { bIsTickable = true; } UThreadTasksLoop::~UThreadTasksLoop() { } bool UThreadTasksLoop::Start() { EAsyncExecution AsyncType = EAsyncExecution::TaskGraph; UThreadTasksLoop* TaskWorker = this; TFunction BodyFunc = [TaskWorker]() { if (TaskWorker != nullptr && TaskWorker->IsValidLowLevel() && IsValid(TaskWorker) && !TaskWorker->IsUnreachable()) { TaskWorker->TaskBody(TaskWorker); if (TaskWorker->TaskDelegate.IsBound()) { TaskWorker->TaskDelegate.Broadcast(); } } }; TFunction OnCompleteFunc = [TaskWorker]() { AsyncTask(ENamedThreads::GameThread, [TaskWorker]() { if (TaskWorker != nullptr && TaskWorker->IsValidLowLevel() && IsValid(TaskWorker) && !TaskWorker->IsUnreachable()) { if (!TaskWorker->IsCanceled()) { TaskWorker->OnComplete(); } else { TaskWorker->Cancel(); } } }); }; Tasks.SetNumZeroed(1); Tasks[0] = Async(AsyncType, TUniqueFunction(BodyFunc), TUniqueFunction(OnCompleteFunc)); // Async functions, it create an new threadpool and execute functions on it. return (true); } bool UThreadTasksLoop::IsRunning() { if (!IsCanceled() && bStarted) { return true; } return false; } void UThreadTasksLoop::TaskBody_Implementation(UThreadTasksLoop* WorkerRef) { while (RepeatTime < BaseLoopNR) { if (WorkerRef != nullptr && WorkerRef->IsValidLowLevel() && IsValid(WorkerRef) && !WorkerRef->IsUnreachable()) { if (WorkerRef->TaskDelegate.IsBound()) { WorkerRef->TaskDelegate.Broadcast(); } } if (!IsInGameThread()) { FPlatformProcess::Sleep(BaseLoopInterval); } RepeatTime++; } if (RepeatTime >= BaseLoopNR) { if (WorkerRef != nullptr && WorkerRef->IsValidLowLevel() && IsValid(WorkerRef) && !WorkerRef->IsUnreachable() && !bCanceled) { WorkerRef->Cancel(); } } } void UThreadTasksLoop::Cancel_Implementation() { RepeatTime = BaseLoopNR; }