[+] AuByteBuffer::SetHeap(...)

[+] AuByteBuffer::Read<AuMemoryViewRead>(...)
[+] AuByteBuffer::Read<AuMemoryViewWrite>(...)
[+] AuByteBuffer::Write<AuMemoryViewRead>(...)
[+] AuByteBuffer::Write<AuMemoryViewWrite>(...)
This commit is contained in:
Reece Wilson 2024-12-11 23:31:11 +00:00
parent 91bcde1443
commit 54021d4fea
5 changed files with 533 additions and 233 deletions

View File

@ -87,71 +87,57 @@ namespace Aurora::Memory
AuUInt8 flagNoFree : 1; /// Prevents all free operations
AuUInt8 flagNoRealloc : 1; /// Prevents a subset of free options, specifically realloc, operations
AuUInt8 flagAlwaysExpandable : 1; /// Internal flag. Do not use.
AuUInt8 flagReserveA : 1; /// Placeholder
AuUInt8 flagAcknowledgeHeap : 1; /// Use pHeap for both memory views *and* ourself. Be careful not to swap out the heap.
AuUInt8 flagReservedB;
///////////////////////////////////////////////////////////////////////
// Special flags/values
///////////////////////////////////////////////////////////////////////
AuUInt8 alignment {}; // Internal value: keeps track of explicit Allocate of alignment values
AuUInt8 alignment {}; // Internal value: keeps track of explicit Allocate of uAlignment values
AuUInt8 scaleSize {}; // TODO:
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Extended pointers
///////////////////////////////////////////////////////////////////////
/// Heap to allocate with
AuHeap *pHeap {};
/**
* @brief Default constructor, allocates an auto-expanding linear bytebuffer
*/
inline ByteBuffer();
inline ByteBuffer(AuUInt uLength, bool circular = false, bool expandable = false);
inline ByteBuffer(AuUInt uLength, AuUInt uAlignment, bool circular = false, bool expandable = false);
inline ByteBuffer(AuHeap *pHeap, AuUInt uLength, bool circular = false, bool expandable = false);
inline ByteBuffer(AuHeap *pHeap, AuUInt uLength, AuUInt uAlignment, bool circular = false, bool expandable = false);
inline ByteBuffer(const MemoryViewRead &readView, bool circular = false, bool expandable = false);
inline ByteBuffer(const MemoryViewRead &readView, AuUInt uAlignment, bool circular = false, bool expandable = false);
template<typename T>
ByteBuffer(T *base, T *end, bool circular = false, bool expandable = false);
/**
* @brief Copy, and if preservePointers, preserve read/write head offsets
* @param buffer
* @param preservePointers
*/
inline ByteBuffer(const ByteBuffer &buffer, bool preservePointers = true);
/**
* @brief Move constructor
* @param buffer
*/
inline ByteBuffer(ByteBuffer &&buffer);
/**
* @brief Copy with possible preserve pointers
* @param buffer
* @param preservePointers
*/
inline ByteBuffer(const ByteBuffer &buffer, bool preservePointers = true);
/**
* @brief Copy pointer range into a new ring or byte buffer
* @param in
* @param length
* @param circular
* @param expandable
*/
inline ByteBuffer(const void *in, AuUInt length, bool circular = false, bool expandable = false);
inline ByteBuffer(const MemoryViewRead &readView, bool circular = false, bool expandable = false);
inline ByteBuffer(const MemoryViewRead &readView, AuUInt uAlignment, bool circular = false, bool expandable = false);
inline ByteBuffer(const AuList<AuUInt8> &vector, bool circular = false, bool expandable = false);
inline ByteBuffer(AuUInt length, bool circular = false, bool expandable = false);
inline ByteBuffer(AuUInt length, AuUInt alignment, bool circular = false, bool expandable = false);
template<typename T>
ByteBuffer(T *base, T *end, bool circular = false, bool expandable = false);
inline ~ByteBuffer()
{
if (this->base && !this->flagNoFree)
{
Free(this->base);
}
}
inline void ResetPositions()
{
this->flagReadError = 0;
this->flagWriteError = 0;
this->readPtr = base;
this->writePtr = base;
}
inline ~ByteBuffer();
// utils: Iterator
@ -192,7 +178,6 @@ namespace Aurora::Memory
// utils: Utils to alternative types
inline auline AuList<AuUInt8> ToVector() const;
inline AuUInt32 GetAllocationPower() const;
inline operator MemoryViewRead() const;
inline operator MemoryViewWrite();
@ -236,51 +221,51 @@ namespace Aurora::Memory
inline auline AuUInt GetWriteOffset() const;
inline auline void ResetReadPointer();
inline auline void ResetWritePointer();
inline auline void ResetPositions(); //...and error flags
inline auline MemoryViewRead GetNextLinearRead();
inline auline MemoryViewWrite GetNextLinearWrite();
inline auline bool CanWrite(AuUInt length);
inline auline bool CanRead(AuUInt length);
inline auline bool CanWrite(AuUInt uLength);
inline auline bool CanRead(AuUInt uLength);
/**
* @brief Returns a linear amount of memory for exactly length of linear bytes
* @param length
* @return
* @brief Returns a linear amount of memory of at least uLength
*/
inline auline MemoryViewRead GetLinearReadableForExactly(AuUInt length)
{
return GetLinearReadable(length);
}
inline auline MemoryViewWrite GetLinearWriteableForExactly(AuUInt length)
{
return GetLinearWriteable(length);
}
inline auline MemoryViewRead GetLinearReadableForAtleast(AuUInt uLength);
inline auline MemoryViewWrite GetLinearWriteableForAtleast(AuUInt uLength);
/**
* @brief Returns a linear amount of memory of at least length
* @param length
* @return
* @brief Returns a linear amount of memory capped to uLength
*/
inline auline MemoryViewRead GetLinearReadableForAtleast(AuUInt length);
inline auline MemoryViewRead GetLinearReadableForNoMore(AuUInt uLength);
inline auline MemoryViewWrite GetLinearWriteableForAtleast(AuUInt length);
inline auline MemoryViewWrite GetLinearWriteableForNoMore(AuUInt uLength);
/**
* @brief Returns a linear amount of memory capped to length
* @param length
* @return
* @brief Returns a linear amount of memory for exactly uLength of linear bytes
*/
inline auline MemoryViewRead GetLinearReadableForNoMore(AuUInt length);
inline auline MemoryViewWrite GetLinearWriteableForNoMore(AuUInt length);
inline auline MemoryViewRead GetLinearReadableForExactly(AuUInt uLength);
inline auline MemoryViewWrite GetLinearWriteableForExactly(AuUInt uLength);
/// legacy: ForExactly variant
inline auline MemoryViewRead GetLinearReadable(AuUInt length);
inline auline MemoryViewRead GetLinearReadable(AuUInt uLength)
{
return GetLinearReadableForExactly(uLength);
}
/// legacy: ForExactly variant
inline auline MemoryViewWrite GetLinearWriteable(AuUInt length);
inline auline MemoryViewWrite GetLinearWriteable(AuUInt uLength)
{
return GetLinearWriteableForExactly(uLength);
}
/**
* @brief
@ -290,20 +275,20 @@ namespace Aurora::Memory
* Where the valid expected uses fall in line with the following truth table:
*
* * PASS
* AuByteBuffer defaultBuffer;
* MyFunction(defaultBuffer);
* AuByteBuffer defaultBuffer; // default constructed, auto expanding
* MyFunction(defaultBuffer); // response in defaultBuffer
* if (defaultBuffer) {}
*
* * FAIL
* AuByteBuffer defaultBuffer;
* AuByteBuffer defaultBuffer; // default constructed, auto expanding
* defaultBuffer.WriteTagged<AuUInt32>(32)
* MyFunction(defaultBuffer);
* MyFunction(defaultBuffer); // !!!, return buffer not empty
* if (defaultBuffer) {}
*
* * FAIL
* AuByteBuffer defaultBuffer;
* AuByteBuffer defaultBuffer; // default constructed, auto expanding
* MyFunction(defaultBuffer);
* MyFunction(defaultBuffer); // !!!
* MyFunction(defaultBuffer); // !!!, return buffer not empty
*
* * PASS
* AuByteBuffer writeStream(512);
@ -311,15 +296,22 @@ namespace Aurora::Memory
* MyFunction(defaultBuffer);
* if (defaultBuffer) {}
*
* @param length
* * PASS
* AuByteBuffer writeStream(512); // not default constructed, not auto-expanding
* writeStream.WriteTagged<AuUInt32>(32)
* MyFunction(defaultBuffer);
* MyFunction(defaultBuffer); // can append in-place to a packet for example
* if (defaultBuffer) {}
*
* @param uLength
* @return
*/
inline auline MemoryViewWrite GetOrAllocateLinearWriteable(AuUInt length);
inline auline MemoryViewWrite GetOrAllocateLinearWriteable(AuUInt uLength);
// Memory operations
inline auline bool Allocate(AuUInt length);
inline auline bool Allocate(AuUInt length, AuUInt alignment);
inline auline bool Allocate(AuUInt uLength);
inline auline bool Allocate(AuUInt uLength, AuUInt uAlignment);
inline auline bool SetBuffer(MemoryViewRead readView, bool bMoveWriteHeadForReaders = true);
/**
@ -334,13 +326,13 @@ namespace Aurora::Memory
inline void Reset();
/**
* @brief Expands the underlying buffer allocation to at least length.
* @brief Expands the underlying buffer allocation to at least uLength.
* Does nothing on failure. Programs can try to allocate in real time
* and handle the write error flag condition from there. To pull the
* real buffer size, see member field allocSize.
* @param length
* @param uLength
*/
inline void Reserve(AuUInt length);
inline void Reserve(AuUInt uLength);
/**
* @brief Is allocated or dummy object?
@ -365,11 +357,11 @@ namespace Aurora::Memory
inline auline bool IsValid() const;
/**
* @brief Allocate at least length bytes, without adjusting the relative read/write head offsets
* @param length
* @brief Allocate at least uLength bytes, without adjusting the relative read/write head offsets
* @param uLength
* @return
*/
inline auline bool Resize(AuUInt length);
inline auline bool Resize(AuUInt uLength);
// Basic Read Write
@ -405,7 +397,7 @@ namespace Aurora::Memory
inline auline AuUInt Read(void *out, AuUInt requestedLength, bool peek = false)
{
return this->WriteLegacy(out, requestedLength, peek);
return this->ReadLegacy(out, requestedLength, peek);
}
#endif
@ -422,7 +414,7 @@ namespace Aurora::Memory
// Utilities
inline bool Trim(AuUInt tail);
inline bool Pad(AuUInt16 aPowOf2, AuUInt8 magicCharacter = '\x00', bool bUpdateWriteHead = true);
inline bool Fill(AuUInt length, AuUInt8 magicCharacter = '\x00');
inline bool Fill(AuUInt uLength, AuUInt8 magicCharacter = '\x00');
// Templated read/write for **PODs**
// (yes, there's some support for non-primitive classes this early into the abstraction.)
@ -434,6 +426,7 @@ namespace Aurora::Memory
template<typename T>
T ReadChecked();
#if defined(AUBUF_DEPR_FUNC)
// requires AUBUF_DEPR_FUNC, otherwise static asserts.
template<typename T>
using ReadHack_t = AuConditional_t<AuIsSame_v<MemoryViewWrite, T>, AuUInt, bool>;
@ -441,29 +434,53 @@ namespace Aurora::Memory
// requires AUBUF_DEPR_FUNC, otherwise static asserts.
template<typename T>
using WriteHack_t = AuConditional_t<AuIsSame_v<MemoryViewRead, T>, AuUInt, bool>;
#else
template<typename T>
using ReadHack_t = bool;
template<typename T>
using WriteHack_t = bool;
#endif
// Writes various data-types to the ByteBuffer.
// Add a [bool/void] Serialize(AuByteBuffer &buffer) to non-primitives to add serial functionality.
// Sets flagWriteError on failure
template<typename T>
WriteHack_t<T> Write(const T &in);
// Writes various data-types to the ByteBuffer.
// Sets flagWriteError on failure
// Add a [bool/void] Serialize(AuByteBuffer &buffer) to non-primitives to add serial functionality.
template<typename T>
WriteHack_t<T> Write(T &in);
// Reads various data-types to the ByteBuffer.
// Add a [bool/void] Deserialize(AuByteBuffer &buffer) to non-primitives to add serial functionality.
// Sets flagReadError on failure
template<typename T>
ReadHack_t<T> Read(T &out);
// Writes various data-types to the ByteBuffer.
// Sets flagWriteError on failure
template<typename T>
bool WriteTagged(const T &in);
// Writes various data-types to the ByteBuffer.
// Sets flagWriteError on failure
template<typename T>
bool WriteTagged(T &in);
// Reads various data-types to the ByteBuffer.
// Sets flagReadError on failure
template<typename T>
bool ReadTagged(T &out);
// Reads various data-types to the ByteBuffer.
// Sets flagReadError on failure
template<typename T>
T ReadTagged();
//
// ignore me
inline AuUInt calcDifferenceBetweenHeadsUnsigned(AuUInt8 *pHeadPointer, AuUInt8 *pSubtrahend)
{
if (pHeadPointer > pSubtrahend)
@ -476,6 +493,7 @@ namespace Aurora::Memory
}
}
// ignore me
inline AuSInt calcDifferenceBetweenHeadsSigned(AuUInt8 *pHeadPointer, AuUInt8 *pSubtrahend)
{
if (pHeadPointer > pSubtrahend)
@ -487,11 +505,15 @@ namespace Aurora::Memory
return -(pSubtrahend - this->base);
}
}
inline bool SetHeap(AuHeap *pHeap);
private:
inline auline bool Allocate2(AuUInt length, AuUInt alignment);
inline auline bool Allocate2(AuUInt length);
inline auline bool Allocate2(AuUInt uLength, AuUInt uAlignment);
inline auline bool Allocate2(AuUInt uLength);
};
// A bytebuffer constructed from an external memory view
struct SharedByteBuffer : ByteBuffer
{
AuSPtr<void> memory;
@ -502,7 +524,7 @@ namespace Aurora::Memory
{
this->allocSize = 0;
this->base = (AuUInt8 *)view.ptr;
this->length = view.length;
this->length = view.uLength;
this->readPtr = this->base;
this->writePtr = this->base;
this->flagNoFree = true;
@ -515,7 +537,7 @@ namespace Aurora::Memory
{
this->allocSize = 0;
this->base = (AuUInt8 *)view.ptr;
this->length = view.length;
this->length = view.uLength;
this->readPtr = this->base;
this->writePtr = this->base;
this->flagNoFree = true;
@ -527,7 +549,7 @@ namespace Aurora::Memory
{
this->allocSize = 0;
this->base = (AuUInt8 *)view.ptr;
this->length = view.length;
this->length = view.uLength;
this->readPtr = this->base;
this->writePtr = this->base + this->length;
this->flagNoFree = true;
@ -541,7 +563,7 @@ namespace Aurora::Memory
{
this->allocSize = 0;
this->base = (AuUInt8 *)view.ptr;
this->length = view.length;
this->length = view.uLength;
this->readPtr = this->base;
this->writePtr = this->base + this->length;
this->flagNoFree = true;
@ -552,6 +574,7 @@ namespace Aurora::Memory
MemoryViewWrite __view;
};
// A bytebuffer that can be deferenced into a memory view whose control block will keep this->SharedFromThis() alive.
struct SharableByteBuffer : ByteBuffer,
AuEnableSharedFromThis<SharableByteBuffer>
{
@ -573,42 +596,16 @@ namespace Aurora::Memory
}
/// @deprecated (partially) (wont remove. AuSPtr<AuMemoryViewXXX>s are now an anti-pattern)
inline AuSPtr<MemoryViewWrite> ToSharedWriteView()
inline SharableByteBuffer(AuHeap *pHeap, AuUInt uLength, bool circular = false, bool expandable = false) :
ByteBuffer(pHeap, uLength, circular, expandable)
{
MemoryViewWrite view = ByteBuffer::operator MemoryViewWrite();
if (!view)
{
return {};
}
if (auto pView = AuMakeShared<MemoryViewWrite>(view.ptr, view.length, &this->uInUseCounter, this->GetSharedBlock()))
inline SharableByteBuffer(AuHeap *pHeap, AuUInt uLength, AuUInt uAlignment, bool circular = false, bool expandable = false) :
ByteBuffer(pHeap, uLength, uAlignment, circular, expandable)
{
return pView;
}
else
{
return {};
}
}
/// @deprecated (partially) (wont remove. AuSPtr<AuMemoryViewXXX>s are now an anti-pattern)
inline AuSPtr<MemoryViewRead> ToSharedReadView() const
{
MemoryViewRead view = ByteBuffer::operator MemoryViewRead();
if (!view)
{
return {};
}
if (auto pView = AuMakeShared<MemoryViewRead>(view.ptr, view.length, (AuAUInt32 *)&this->uInUseCounter, this->GetSharedBlock()))
{
return pView;
}
else
{
return {};
}
}
inline MemoryViewWrite ToSafeWriteView()
@ -619,7 +616,7 @@ namespace Aurora::Memory
return {};
}
return MemoryViewWrite(view.ptr, view.length, &this->uInUseCounter, this->GetSharedBlock());
return MemoryViewWrite(view.ptr, view.uLength, &this->uInUseCounter, this->GetSharedBlock());
}
inline MemoryViewRead ToSafeReadView() const
@ -630,7 +627,7 @@ namespace Aurora::Memory
return {};
}
return MemoryViewRead(view.ptr, view.length, (AuAUInt32 *)&this->uInUseCounter, this->GetSharedBlock());
return MemoryViewRead(view.ptr, view.uLength, (AuAUInt32 *)&this->uInUseCounter, this->GetSharedBlock());
}
inline operator AuSPtr<MemoryViewWrite>()
@ -653,32 +650,64 @@ namespace Aurora::Memory
return this->ToSafeReadView();
}
/// @deprecated (partially) (wont remove. AuSPtr<AuMemoryViewXXX>s are now an anti-pattern)
inline AuSPtr<MemoryViewWrite> ToSharedWriteView()
{
MemoryViewWrite view = ByteBuffer::operator MemoryViewWrite();
if (!view)
{
return {};
}
if (auto pView = AuMakeShared<MemoryViewWrite>(view.ptr, view.uLength, &this->uInUseCounter, this->GetSharedBlock()))
{
return pView;
}
else
{
return {};
}
}
/// @deprecated (partially) (wont remove. AuSPtr<AuMemoryViewXXX>s are now an anti-pattern)
inline AuSPtr<MemoryViewRead> ToSharedReadView() const
{
MemoryViewRead view = ByteBuffer::operator MemoryViewRead();
if (!view)
{
return {};
}
if (auto pView = AuMakeShared<MemoryViewRead>(view.ptr, view.uLength, (AuAUInt32 *)&this->uInUseCounter, this->GetSharedBlock()))
{
return pView;
}
else
{
return {};
}
}
private:
// TODO: under const methods, AuSharedFromThis, the static pointer cast, and the AuMemoryView constructor is hopelessly broken
// I've always considered c++s constness fundamentally flawed and designed by idiots. I'm not sinking time into fixes these yet.
// This should be just an AuSharedFromThis()
// But, no, Java, C++, and everybody else gets constness wrong to solve a series of bugs * that can be solved with simple encapsulation *
// (DOP + encapsulated API boundaries ftw)
// I dont care to fix this, or use the stupid mutable keyword on the usage counter, for now. It's a waste of my time.
AuSPtr<void> GetSharedBlock() const
{
return AuSPtr<void>(this->shared_from_this(), (void *)this);
}
};
static ByteBuffer NewResizableBuffer(AuUInt32 length = 0)
static ByteBuffer NewResizableBuffer(AuUInt32 uLength = 0)
{
return ByteBuffer(length, false, true);
return ByteBuffer(uLength, false, true);
}
static ByteBuffer NewRingBuffer(AuUInt32 length = 1024 * 5)
static ByteBuffer NewRingBuffer(AuUInt32 uLength = 1024 * 5)
{
return ByteBuffer(length, true, false);
return ByteBuffer(uLength, true, false);
}
static AuSPtr<SharableByteBuffer> NewSharableResizableBuffer(AuUInt32 length = 0)
static AuSPtr<SharableByteBuffer> NewSharableResizableBuffer(AuUInt32 uLength = 0)
{
auto pThat = AuMakeShared<SharableByteBuffer>(length, false, true);
auto pThat = AuMakeShared<SharableByteBuffer>(uLength, false, true);
if (!(pThat && *pThat))
{
return {};
@ -686,9 +715,9 @@ namespace Aurora::Memory
return pThat;
}
static AuSPtr<SharableByteBuffer> NewSharableBuffer(AuUInt32 length = 0)
static AuSPtr<SharableByteBuffer> NewSharableBuffer(AuUInt32 uLength = 0)
{
auto pThat = AuMakeShared<SharableByteBuffer>(length);
auto pThat = AuMakeShared<SharableByteBuffer>(uLength);
if (!(pThat && *pThat))
{
return {};

View File

@ -26,7 +26,14 @@ namespace Aurora::Memory
if (this->base)
{
Free(this->base);
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->pHeap->Free(this->base);
}
else
{
Memory::Free(this->base);
}
this->base = nullptr;
}
@ -39,13 +46,27 @@ namespace Aurora::Memory
return true;
}
if (this->flagAcknowledgeHeap && this->pHeap)
{
if (this->alignment)
{
this->base = ZAlloc<AuUInt8 *>(length, this->alignment);
this->base = this->pHeap->ZAlloc<AuUInt8 *>(length, this->alignment);
}
else
{
this->base = ZAlloc<AuUInt8 *>(length);
this->base = this->pHeap->ZAlloc<AuUInt8 *>(length);
}
}
else
{
if (this->alignment)
{
this->base = Memory::ZAlloc<AuUInt8 *>(length, this->alignment);
}
else
{
this->base = Memory::ZAlloc<AuUInt8 *>(length);
}
}
if (!this->base)
@ -76,7 +97,14 @@ namespace Aurora::Memory
if (this->base)
{
Free(this->base);
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->pHeap->Free(this->base);
}
else
{
Memory::Free(this->base);
}
this->base = nullptr;
}
@ -89,7 +117,14 @@ namespace Aurora::Memory
return true;
}
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->base = this->pHeap->ZAlloc<AuUInt8 *>(length, alignment);
}
else
{
this->base = ZAlloc<AuUInt8 *>(length, alignment);
}
if (!this->base)
{
return false;
@ -146,8 +181,16 @@ namespace Aurora::Memory
if (this->base && !this->flagNoFree)
{
Free(this->base);
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->pHeap->Free(this->base);
}
else
{
Memory::Free(this->base);
}
this->base = {};
this->pHeap = {};
}
this->base = {};
@ -182,8 +225,15 @@ namespace Aurora::Memory
if (this->base &&
this->length == 0)
{
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->pHeap->Free(this->base);
}
else
{
Memory::Free(this->base);
}
this->base = nullptr;
this->allocSize = 0;
this->readPtr = nullptr;
@ -210,6 +260,19 @@ namespace Aurora::Memory
auto uWriteOffset = this->writePtr - this->base;
AuUInt8 *pNext {};
if (this->flagAcknowledgeHeap && this->pHeap)
{
if (this->alignment)
{
pNext = this->pHeap->ZReallocEx(this->base, this->length, this->alignment, true);
}
else
{
pNext = this->pHeap->ZReallocEx(this->base, this->length, true);
}
}
else
{
if (this->alignment)
{
pNext = Memory::ZReallocEx(this->base, this->length, this->alignment, true);
@ -218,6 +281,7 @@ namespace Aurora::Memory
{
pNext = Memory::ZReallocEx(this->base, this->length, true);
}
}
if (!pNext)
{
@ -277,13 +341,28 @@ namespace Aurora::Memory
auto newLength = AuMax(length, AuPageRoundUp(this->allocSize + (this->allocSize / 3), AuUInt(128)));
AuUInt8 *pNext {};
if (this->flagAcknowledgeHeap && this->pHeap)
{
if (this->alignment)
{
pNext = ZRealloc(this->base, newLength, this->alignment);
pNext = this->pHeap->ZRealloc(this->base, newLength, this->alignment);
}
else
{
pNext = ZRealloc(this->base, newLength);
pNext = this->pHeap->ZRealloc(this->base, newLength);
}
}
else
{
if (this->alignment)
{
pNext = Memory::ZRealloc(this->base, newLength, this->alignment);
}
else
{
pNext = Memory::ZRealloc(this->base, newLength);
}
}
if (pNext)
@ -297,11 +376,21 @@ namespace Aurora::Memory
}
}
ByteBuffer replacement(length, this->alignment, (bool)this->flagCircular, (bool)this->flagExpandable);
ByteBuffer replacement(this->pHeap,
length,
this->alignment,
(bool)this->flagCircular,
(bool)this->flagExpandable);
if (!replacement)
{
return false;
}
if (!this->pHeap)
{
replacement.flagAcknowledgeHeap = 0;
}
replacement.flagAlwaysExpandable = this->flagAlwaysExpandable;
AuUInt uBytesRem {};
@ -320,4 +409,32 @@ namespace Aurora::Memory
this->operator=(AuMove(replacement));
return true;
}
bool ByteBuffer::SetHeap(AuHeap *pHeap)
{
__audetail::BufferAllocLock lock(this);
if (!this->IsEmpty())
{
return false;
}
this->pHeap = pHeap;
return true;
}
ByteBuffer::~ByteBuffer()
{
if (this->base && !this->flagNoFree)
{
if (this->flagAcknowledgeHeap && this->pHeap)
{
this->pHeap->Free(this->base);
}
else
{
Memory::Free(this->base);
}
}
}
}

View File

@ -227,6 +227,29 @@ namespace Aurora::Memory
this->readPtr = this->base;
}
void ByteBuffer::ResetWritePointer()
{
if (this->flagCircular)
{
this->writePtr = this->readPtr;
}
else
{
this->writePtr = this->base;
}
}
void ByteBuffer::ResetPositions()
{
this->flagReadError = 0;
if (!this->flagNoRealloc)
{
this->flagWriteError = 0;
}
this->readPtr = this->base;
this->writePtr = this->base;
}
MemoryViewRead ByteBuffer::GetNextLinearRead()
{
__audetail::BufferAllocLock lock(this);
@ -371,14 +394,14 @@ namespace Aurora::Memory
}
/* exactly */
MemoryViewRead ByteBuffer::GetLinearReadable(AuUInt length)
MemoryViewRead ByteBuffer::GetLinearReadableForExactly(AuUInt length)
{
auto view = this->GetNextLinearRead();
return view.length < length ? MemoryViewRead {} : MemoryViewRead(view.ptr, length, &this->uInUseCounter);
}
/* exactly */
MemoryViewWrite ByteBuffer::GetLinearWriteable(AuUInt length)
MemoryViewWrite ByteBuffer::GetLinearWriteableForExactly(AuUInt length)
{
auto view = this->GetNextLinearWrite();
if (this->flagAlwaysExpandable &&

View File

@ -154,10 +154,99 @@ namespace Aurora::Memory
{
if constexpr (AuIsClass_v<T>)
{
#if defined(AUBUF_DEPR_FUNC)
if constexpr (AuIsSame_v<T, MemoryViewWrite>)
#else
if constexpr (AuIsSame_v<T, MemoryViewWrite> ||
AuIsSame_v<T, MemoryViewRead>)
#endif
{
#if !defined(AUBUF_DEPR_FUNC)
static_assert(AuIsSame_v<T, MemoryViewWrite>);
out = {};
AuUInt64 uLength;
if (!this->Read<AuUInt64>(uLength))
{
return false;
}
if (!uLength)
{
return true;
}
#if !defined(AURORA_IS_64BIT)
if (uLength & 0xFFFFFFFF00000000ull)
{
this->flagReadError = true;
return false;
}
#endif
#if !defined(AURORA_BUFFER_NO_SANE_ELEMENTS_FOR_VIEWS)
if (uLength > kMaxSaneElementsForAuMemory)
{
this->flagReadError = true;
return false;
}
#endif
AuSPtr<AuUInt8> pData;
if (this->pHeap)
{
if (this->alignment)
{
pData = this->pHeap->NewClassArray2<AuUInt8>(uLength, this->alignment);
}
else
{
pData = this->pHeap->NewClassArray<AuUInt8>(uLength);
}
}
else
{
if (this->alignment)
{
pData = AuMemory::GetDefaultDiscontiguousHeap()->NewClassArray2<AuUInt8>(uLength, this->alignment);
}
else
{
pData = AuMemory::GetDefaultDiscontiguousHeap()->NewClassArray<AuUInt8>(uLength);
}
}
if (!pData)
{
return {};
}
AuUInt8 * pRaw { pData.get() };
AuUInt uToRead { uLength };
AuUInt uOffset { };
while (*this && uToRead)
{
AuMemoryViewRead toClone = this->GetLinearReadableForNoMore(uToRead);
if (toClone.length == 0)
{
break;
}
AuMemcpy(pRaw + uOffset, toClone.Begin(), toClone.length);
uToRead -= toClone.length;
uOffset += toClone.length;
this->readPtr += toClone.length;
}
if (uOffset != uLength)
{
this->flagReadError = true;
return false;
}
out = T(T(pData.get(), uLength), pData);
return true;
#else
return Read(out.ptr, out.length);
#endif
@ -343,12 +432,20 @@ namespace Aurora::Memory
{
if constexpr (AuIsClass_v<T>)
{
#if defined(AUBUF_DEPR_FUNC)
if constexpr (AuIsSame_v<T, MemoryViewRead>)
#else
if constexpr (AuIsSame_v<T, MemoryViewWrite> ||
AuIsSame_v<T, MemoryViewRead>)
#endif
{
#if !defined(AUBUF_DEPR_FUNC)
static_assert(AuIsSame_v<T, MemoryViewRead>);
Write<AuUInt64>(in.Length());
WriteChecked(AuMemoryViewRead { in.Begin(), in.Length() });
return !this->flagWriteError;
#else
return Write(in.ptr, in.length);
return WriteLegacy(in.ptr, in.length);
#endif
}
else if constexpr (__detail::AuHasSerializeBool<AuRemoveReference_t<T>>::type::value ||
@ -386,9 +483,20 @@ namespace Aurora::Memory
{
if constexpr (AuIsClass_v<T>)
{
#if defined(AUBUF_DEPR_FUNC)
if constexpr (AuIsSame_v<T, MemoryViewRead>)
#else
if constexpr (AuIsSame_v<T, MemoryViewWrite> ||
AuIsSame_v<T, MemoryViewRead>)
#endif
{
return Write(in.ptr, in.length);
#if !defined(AUBUF_DEPR_FUNC)
Write<AuUInt64>(in.Length());
WriteChecked(AuMemoryViewRead { in.Begin(), in.Length() });
return !this->flagWriteError;
#else
return WriteLegacy(in.ptr, in.length);
#endif
}
else if constexpr (__detail::AuHasSerializeBool2<AuRemoveReference_t<T>>::type::value)
{

View File

@ -142,11 +142,6 @@ namespace Aurora::Memory
return cend();
}
AuUInt32 ByteBuffer::GetAllocationPower() const
{
return AuUInt32(1) << (AuUInt32(this->scaleSize));
}
ByteBuffer::operator MemoryViewRead() const
{
return MemoryViewRead(cbegin(), cend(), (AuAUInt32 *)&this->uInUseCounter);
@ -197,7 +192,7 @@ namespace Aurora::Memory
ByteBuffer::ByteBuffer(ByteBuffer &&buffer) :
flagCircular {}, flagExpandable {}, flagReadError {}, flagWriteError {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA{}, flagReservedB {}
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap{}, flagReservedB {}
{
this->base = buffer.base;
this->length = buffer.length;
@ -211,6 +206,7 @@ namespace Aurora::Memory
this->flagWriteError = buffer.flagWriteError;
this->alignment = buffer.alignment;
this->flagReservedB = buffer.flagReservedB;
this->pHeap = buffer.pHeap;
buffer.base = {};
buffer.length = {};
buffer.allocSize = {};
@ -221,11 +217,12 @@ namespace Aurora::Memory
buffer.flagAlwaysExpandable = {};
buffer.scaleSize = {};
buffer.alignment = {};
buffer.pHeap = {};
}
ByteBuffer::ByteBuffer(const ByteBuffer &buffer, bool preservePointers) :
flagCircular {}, flagExpandable { }, flagReadError {}, flagWriteError {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}
{
if (buffer.length)
{
@ -262,31 +259,8 @@ namespace Aurora::Memory
AuMemcpy(this->base, buffer.base, this->length);
}
ByteBuffer::ByteBuffer(const void *in, AuUInt length, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
this->base = length ? ZAlloc<AuUInt8 *>(length) : nullptr;
if (!this->base)
{
Reset();
return;
}
if (!in)
{
Reset();
return;
}
this->length = length;
this->allocSize = length;
this->readPtr = this->base;
this->writePtr = this->readPtr + this->length;
AuMemcpy(this->base, in, this->length);
}
ByteBuffer::ByteBuffer(const MemoryViewRead &readView, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
@ -303,26 +277,8 @@ namespace Aurora::Memory
AuMemcpy(this->base, readView.Begin(), this->length);
}
ByteBuffer::ByteBuffer(const AuList<AuUInt8> &vector, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
this->base = vector.size() ? ZAlloc<AuUInt8 *>(vector.size()) : nullptr;
if (!this->base)
{
Reset();
return;
}
this->length = vector.size();
this->allocSize = this->length;
this->readPtr = this->base;
this->writePtr = this->readPtr + this->length;
AuMemcpy(this->base, vector.data(), this->length);
}
ByteBuffer::ByteBuffer(const MemoryViewRead &readView, AuUInt uAlignment, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
@ -345,7 +301,7 @@ namespace Aurora::Memory
}
ByteBuffer::ByteBuffer(AuUInt length, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
this->scaleSize = kBufferInitialPower;
@ -367,7 +323,7 @@ namespace Aurora::Memory
}
ByteBuffer::ByteBuffer(AuUInt length, AuUInt alignment, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
if (!length)
@ -389,9 +345,73 @@ namespace Aurora::Memory
this->writePtr = this->base;
}
ByteBuffer::ByteBuffer(AuHeap *pHeap, AuUInt length, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0),
flagAcknowledgeHeap(1)
{
this->scaleSize = kBufferInitialPower;
if (!length)
{
Reset();
return;
}
if (pHeap)
{
this->base = pHeap->ZAlloc<AuUInt8 *>(length);
}
else
{
this->base = Memory::ZAlloc<AuUInt8 *>(length);
}
if (!this->base)
{
Reset();
return;
}
this->length = length;
this->allocSize = length;
this->readPtr = this->base;
this->writePtr = this->base;
this->pHeap = pHeap;
}
ByteBuffer::ByteBuffer(AuHeap *pHeap, AuUInt length, AuUInt alignment, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0),
flagAcknowledgeHeap(1)
{
if (!length)
{
Reset();
return;
}
this->scaleSize = kBufferInitialPower;
if (pHeap)
{
this->base = pHeap->ZAlloc<AuUInt8 *>(length, alignment);
}
else
{
this->base = Memory::ZAlloc<AuUInt8 *>(length, alignment);
}
if (!this->base)
{
Reset();
return;
}
this->alignment = alignment;
this->length = length;
this->allocSize = length;
this->readPtr = this->base;
this->writePtr = this->base;
this->pHeap = pHeap;
}
template<typename T>
ByteBuffer::ByteBuffer(T *base, T *end, bool circular, bool expandable) :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0)
{
if (!base)
@ -420,7 +440,7 @@ namespace Aurora::Memory
}
ByteBuffer::ByteBuffer() :
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagReserveA {}, flagReservedB {},
flagNoFree {}, flagNoRealloc {}, flagAlwaysExpandable {}, flagAcknowledgeHeap {}, flagReservedB {},
flagCircular(0), flagExpandable(true), flagReadError(0), flagWriteError(0)
{
this->base = {};
@ -446,6 +466,7 @@ namespace Aurora::Memory
this->flagNoFree = other.flagNoFree;
this->scaleSize = other.scaleSize;
this->flagReservedB = other.flagReservedB;
this->pHeap = other.pHeap;
other.base = {};
other.length = {};
other.allocSize = {};
@ -462,6 +483,8 @@ namespace Aurora::Memory
ByteBuffer &ByteBuffer::operator =(const ByteBuffer &buffer)
{
this->pHeap = buffer.pHeap;
if (!buffer.length)
{
AuResetMember(*this);