EM_Task/AssetRegistry/Private/BackgroundGatherResults.h
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

119 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
/**
* This is a specialized container for storing the results of the asset gather process.
* Internally it is an array, but it acts like a FIFO queue. Items are pushed and appended, and then popped off for processing.
* The difference between it and a standard queue are that the popped items aren't removed until the container is trimmed,
* which allows multiple results to be processed per-trim with a minimal amount of array reshuffling (since we're removing from the front).
*/
template <typename T, typename Allocator = FDefaultAllocator>
class TBackgroundGatherResults
{
public:
/** Constructor. */
TBackgroundGatherResults()
: PoppedCount(0)
{
}
/** Push the given item onto the end of the queue. */
FORCEINLINE void Push(const T& Item)
{
InternalQueue.Add(Item);
}
/** Push the given item onto the end of the queue. */
FORCEINLINE void Push(T&& Item)
{
InternalQueue.Add(MoveTemp(Item));
}
/** Append the given items onto the end of the queue. */
FORCEINLINE void Append(const TArray<T>& Items)
{
InternalQueue.Append(Items);
}
/** Append the given items onto the end of the queue. */
FORCEINLINE void Append(TArray<T>&& Items)
{
InternalQueue.Append(MoveTemp(Items));
}
/** Pop an item from the front of the queue. The returned data is valid until the queue is trimmed. */
FORCEINLINE T& Pop()
{
return InternalQueue[PoppedCount++];
}
/** Trim any popped items from this queue. */
FORCEINLINE void Trim()
{
if (PoppedCount > 0)
{
InternalQueue.RemoveAt(0, PoppedCount);
PoppedCount = 0;
}
}
/** Get the number of items left to process in this queue. */
FORCEINLINE int32 Num() const
{
return InternalQueue.Num() - PoppedCount;
}
/** Empty the queue, keeping the current allocation. */
FORCEINLINE void Reset()
{
PoppedCount = 0;
InternalQueue.Reset();
}
/** Empty the queue, discarding the current allocation. */
FORCEINLINE void Empty()
{
PoppedCount = 0;
InternalQueue.Empty();
}
/** Gets the size of the current allocation */
FORCEINLINE uint32 GetAllocatedSize() const
{
return InternalQueue.GetAllocatedSize();
}
/** Array access operator */
FORCEINLINE T& operator[](int32 Index)
{
check(Index >= 0 && Index < Num());
return InternalQueue[Index + PoppedCount];
}
/** Prioritize any items that pass the given predicate to be at the front of the queue. */
void Prioritize(TFunctionRef<bool(const T&)> Pred)
{
int32 LowestNonPriorityIdx = PoppedCount;
for (int32 Idx = PoppedCount; Idx < InternalQueue.Num(); ++Idx)
{
if (Pred(InternalQueue[Idx]))
{
InternalQueue.Swap(Idx, LowestNonPriorityIdx++);
}
}
}
private:
typedef TArray<T, Allocator> InternalQueueType;
private:
/** Number of items that have been popped off the queue without it being trimmed. Items before this count should not be mutated, and we should trim to this number. */
int32 PoppedCount;
/** Internal FIFO queue of data. */
InternalQueueType InternalQueue;
};