Files
UnrealEngine/Engine/Source/Programs/Unsync/Private/UnsyncBuffer.cpp
2025-05-18 13:04:45 +08:00

183 lines
3.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UnsyncBuffer.h"
#include "UnsyncMemory.h"
namespace unsync {
FBuffer::FBuffer(uint64 InitialSize)
{
Resize(InitialSize);
}
FBuffer::FBuffer(uint64 InitialSize, uint8 Value)
{
Resize(InitialSize);
memset(Buffer, Value, InitialSize);
}
FBuffer::FBuffer(std::initializer_list<uint8> Values)
{
if (Values.size())
{
Resize(Values.size());
memcpy(Buffer, Values.begin(), Values.size());
}
}
FBuffer::FBuffer(FBuffer&& Rhs)
{
std::swap(Buffer, Rhs.Buffer);
std::swap(BufferSize, Rhs.BufferSize);
std::swap(BufferCapacity, Rhs.BufferCapacity);
}
FBuffer&
FBuffer::operator=(FBuffer&& Rhs)
{
if (&Rhs != this)
{
std::swap(Buffer, Rhs.Buffer);
std::swap(BufferSize, Rhs.BufferSize);
std::swap(BufferCapacity, Rhs.BufferCapacity);
Rhs.Clear();
}
return *this;
}
FBuffer::~FBuffer()
{
UnsyncFree(Buffer);
UNSYNC_CLOBBER(Buffer);
}
void
FBuffer::Reserve(uint64 RequiredCapacity)
{
uint64 AlignedRequiredCapacity = std::max<uint64>(16, RequiredCapacity);
EnsureCapacity(AlignedRequiredCapacity);
}
void
FBuffer::Append(const FBuffer& Other)
{
Append(Other.Data(), Other.Size());
}
void
FBuffer::Append(const FBufferView& Other)
{
Append(Other.Data, Other.Size);
}
void
FBuffer::Append(const uint8* AppendData, uint64 AppendSize)
{
uint64 RequiredCapacity = BufferSize + AppendSize;
uint64 AlignedRequiredCapacity = std::max<uint64>(16, BufferCapacity);
while (AlignedRequiredCapacity < RequiredCapacity)
{
AlignedRequiredCapacity *= 2;
}
EnsureCapacity(AlignedRequiredCapacity);
memcpy(Buffer + BufferSize, AppendData, AppendSize);
BufferSize += AppendSize;
}
void
FBuffer::Shrink()
{
if (BufferSize < BufferCapacity)
{
uint8* NewBuffer = nullptr;
if (BufferSize)
{
NewBuffer = (uint8*)UnsyncMalloc(BufferSize);
UNSYNC_ASSERT(NewBuffer);
memcpy(NewBuffer, Buffer, BufferSize);
}
UnsyncFree(Buffer);
Buffer = NewBuffer;
BufferCapacity = BufferSize;
}
}
void
FBuffer::Resize(uint64 NewSize)
{
if (NewSize > BufferSize)
{
EnsureCapacity(NewSize);
}
BufferSize = NewSize;
}
void
FBuffer::EnsureCapacity(uint64 RequiredCapacity)
{
if (RequiredCapacity > BufferCapacity)
{
uint8* NewBuffer = (uint8*)UnsyncMalloc(RequiredCapacity);
UNSYNC_ASSERT(NewBuffer);
if (BufferSize)
{
memcpy(NewBuffer, Buffer, BufferSize);
UnsyncFree(Buffer);
}
Buffer = NewBuffer;
BufferCapacity = RequiredCapacity;
}
}
FBufferPool::FBufferPool(uint64 InMaxBufferSize) : MaxBufferSize(InMaxBufferSize)
{
}
FBufferPool::~FBufferPool()
{
std::lock_guard<std::mutex> LockGuard(Mutex);
UNSYNC_ASSERT(AllocatedBuffers == 0);
for (FBuffer* It : Pool)
{
delete It;
}
}
FBuffer*
FBufferPool::Acquire()
{
std::lock_guard<std::mutex> LockGuard(Mutex);
if (Pool.empty())
{
Pool.push_back(new FBuffer(MaxBufferSize));
}
FBuffer* TResult = Pool.back();
Pool.pop_back();
++AllocatedBuffers;
return TResult;
}
void
FBufferPool::Release(FBuffer* Buffer)
{
std::lock_guard<std::mutex> LockGuard(Mutex);
UNSYNC_ASSERT(Buffer->Size() == MaxBufferSize);
Pool.push_back(Buffer);
--AllocatedBuffers;
}
} // namespace unsync