[+] AuMemory::SharedByteBuffer
[+] AuMemory::ByteBuffer.flagNoFree [*] SetBuffer(MemoryViewRead readView, bool bMoveWriteHeadForReaders = true); ...added bMoveWriteHeadForReaders [-] AuMemory::SetBuffer(const void *in, AuUInt length) [-] AuMemory::SetBuffer(const AuList<AuUInt8> &buffer) [*] Harden AuMemory::ByteBuffer::RemainingBytes bc it is a high level api that is not called excessively. Invalid head states should not mess with ::CanRead/::CanWrite [*] Harden AuMemory::ByteBuffer::RemainingWrite bc it is a high level api that is not called excessively. Invalid head states should not mess with ::CanRead/::CanWrite
This commit is contained in:
parent
e0d672ae9b
commit
37472e508e
@ -78,6 +78,7 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
AuUInt8 flagReadError : 1 {};
|
AuUInt8 flagReadError : 1 {};
|
||||||
AuUInt8 flagWriteError : 1 {};
|
AuUInt8 flagWriteError : 1 {};
|
||||||
|
AuUInt8 flagNoFree : 1 {};
|
||||||
// TODO: flag: allow circular overrun to allow for 100% access of the buffer from either read head
|
// TODO: flag: allow circular overrun to allow for 100% access of the buffer from either read head
|
||||||
// - implicit padding
|
// - implicit padding
|
||||||
AuUInt8 scaleSize {};//
|
AuUInt8 scaleSize {};//
|
||||||
@ -388,9 +389,7 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
inline auline bool Allocate(AuUInt length, bool fast = true);
|
inline auline bool Allocate(AuUInt length, bool fast = true);
|
||||||
inline auline bool Allocate(AuUInt length, AuUInt alignment, bool fast = true);
|
inline auline bool Allocate(AuUInt length, AuUInt alignment, bool fast = true);
|
||||||
inline auline bool SetBuffer(MemoryViewRead readView);
|
inline auline bool SetBuffer(MemoryViewRead readView, bool bMoveWriteHeadForReaders = true);
|
||||||
inline auline bool SetBuffer(const void *in, AuUInt length);
|
|
||||||
inline auline bool SetBuffer(const AuList<AuUInt8> &buffer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Releases excess memory (like, shrink to fit in c++)
|
* @brief Releases excess memory (like, shrink to fit in c++)
|
||||||
@ -481,4 +480,31 @@ namespace Aurora::Memory
|
|||||||
{
|
{
|
||||||
return ByteBuffer(length, true, false);
|
return ByteBuffer(length, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SharedByteBuffer : ByteBuffer
|
||||||
|
{
|
||||||
|
AuSPtr<void> memory;
|
||||||
|
|
||||||
|
inline SharedByteBuffer(AuSPtr<MemoryViewWrite> pReadView) : ByteBuffer()
|
||||||
|
{
|
||||||
|
this->allocSize = 0;
|
||||||
|
this->base = (AuUInt8 *)pReadView->ptr;
|
||||||
|
this->length = pReadView->length;
|
||||||
|
this->readPtr = this->base;
|
||||||
|
this->writePtr = this->base + this->length;
|
||||||
|
this->flagNoFree = true;
|
||||||
|
this->memory = pReadView;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SharedByteBuffer(AuSPtr<void> pRAIIParentOwner, MemoryViewWrite view) : ByteBuffer()
|
||||||
|
{
|
||||||
|
this->allocSize = 0;
|
||||||
|
this->base = (AuUInt8 *)view.ptr;
|
||||||
|
this->length = view.length;
|
||||||
|
this->readPtr = this->base;
|
||||||
|
this->writePtr = this->base + this->length;
|
||||||
|
this->flagNoFree = true;
|
||||||
|
this->memory = pRAIIParentOwner;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
@ -11,6 +11,11 @@ namespace Aurora::Memory
|
|||||||
{
|
{
|
||||||
bool ByteBuffer::Allocate(AuUInt length, bool fast)
|
bool ByteBuffer::Allocate(AuUInt length, bool fast)
|
||||||
{
|
{
|
||||||
|
if (this->flagNoFree)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->base)
|
if (this->base)
|
||||||
{
|
{
|
||||||
Free(this->base);
|
Free(this->base);
|
||||||
@ -40,6 +45,11 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
bool ByteBuffer::Allocate(AuUInt length, AuUInt alignment, bool fast)
|
bool ByteBuffer::Allocate(AuUInt length, AuUInt alignment, bool fast)
|
||||||
{
|
{
|
||||||
|
if (this->flagNoFree)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->base)
|
if (this->base)
|
||||||
{
|
{
|
||||||
Free(this->base);
|
Free(this->base);
|
||||||
@ -68,8 +78,13 @@ namespace Aurora::Memory
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ByteBuffer::SetBuffer(MemoryViewRead readView)
|
bool ByteBuffer::SetBuffer(MemoryViewRead readView, bool bMoveWriteHeadForReaders)
|
||||||
{
|
{
|
||||||
|
if (this->flagNoFree)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Allocate(readView.length))
|
if (!Allocate(readView.length))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -81,28 +96,19 @@ namespace Aurora::Memory
|
|||||||
}
|
}
|
||||||
|
|
||||||
AuMemcpy(this->base, readView.ptr, this->length);
|
AuMemcpy(this->base, readView.ptr, this->length);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ByteBuffer::SetBuffer(const void *in, AuUInt length)
|
if (bMoveWriteHeadForReaders)
|
||||||
{
|
|
||||||
if (!Allocate(length))
|
|
||||||
{
|
{
|
||||||
return false;
|
this->readPtr = this->base;
|
||||||
|
this->writePtr = this->base + this->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuMemcpy(this->base, in, this->length);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ByteBuffer::SetBuffer(const AuList<AuUInt8> &buffer)
|
|
||||||
{
|
|
||||||
return SetBuffer(buffer.data(), buffer.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ByteBuffer::Reset()
|
void ByteBuffer::Reset()
|
||||||
{
|
{
|
||||||
if (this->base)
|
if (this->base && !this->flagNoFree)
|
||||||
{
|
{
|
||||||
Free(this->base);
|
Free(this->base);
|
||||||
this->base = {};
|
this->base = {};
|
||||||
@ -128,6 +134,11 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
void ByteBuffer::GC()
|
void ByteBuffer::GC()
|
||||||
{
|
{
|
||||||
|
if (this->flagNoFree)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->base)
|
if (!this->base)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -151,6 +162,11 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
bool ByteBuffer::Resize(AuUInt length)
|
bool ByteBuffer::Resize(AuUInt length)
|
||||||
{
|
{
|
||||||
|
if (this->flagNoFree)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AuUInt oldWriteIdx, oldReadIdx, oldLength, newLength;
|
AuUInt oldWriteIdx, oldReadIdx, oldLength, newLength;
|
||||||
AuUInt8 *nextRead, *nextWrite, *nextPtr;
|
AuUInt8 *nextRead, *nextWrite, *nextPtr;
|
||||||
|
|
||||||
|
@ -97,20 +97,45 @@ namespace Aurora::Memory
|
|||||||
|
|
||||||
AuUInt ByteBuffer::RemainingBytes(bool endAtWrite) const
|
AuUInt ByteBuffer::RemainingBytes(bool endAtWrite) const
|
||||||
{
|
{
|
||||||
if (flagCircular)
|
// sanity:
|
||||||
|
|
||||||
|
if (this->writePtr > this->base + this->length)
|
||||||
{
|
{
|
||||||
if (readPtr == writePtr)
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->writePtr < this->base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->readPtr > this->base + this->length)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->readPtr < this->base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
|
||||||
|
if (this->flagCircular)
|
||||||
|
{
|
||||||
|
if (this->readPtr == this->writePtr)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if ((readPtr < writePtr) && (endAtWrite))
|
else if ((this->readPtr < this->writePtr) && (endAtWrite))
|
||||||
{
|
{
|
||||||
return writePtr - readPtr;
|
return this->writePtr - this->readPtr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto linearOverhead = length - (readPtr - base);
|
// you should be able to read the entirety of the buffer - writers cannot to prevent overflows
|
||||||
auto toWriteOverhead = writePtr - base;
|
auto linearOverhead = this->length - (this->readPtr - this->base);
|
||||||
|
auto toWriteOverhead = this->writePtr - this->base;
|
||||||
return linearOverhead + toWriteOverhead;
|
return linearOverhead + toWriteOverhead;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,24 +143,48 @@ namespace Aurora::Memory
|
|||||||
{
|
{
|
||||||
if (endAtWrite)
|
if (endAtWrite)
|
||||||
{
|
{
|
||||||
if (writePtr < readPtr)
|
if (this->writePtr < this->readPtr)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return writePtr - readPtr;
|
return this->writePtr - this->readPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (length - (readPtr - base));
|
return (this->length - (this->readPtr - this->base));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AuUInt ByteBuffer::RemainingWrite(bool endAtRead) const
|
AuUInt ByteBuffer::RemainingWrite(bool endAtRead) const
|
||||||
{
|
{
|
||||||
|
// sanity:
|
||||||
|
|
||||||
|
if (this->writePtr > this->base + this->length)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->writePtr < this->base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->readPtr > this->base + this->length)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->readPtr < this->base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////
|
||||||
|
|
||||||
if (this->flagCircular)
|
if (this->flagCircular)
|
||||||
{
|
{
|
||||||
if (this->readPtr == this->writePtr)
|
if (this->readPtr == this->writePtr)
|
||||||
@ -144,12 +193,14 @@ namespace Aurora::Memory
|
|||||||
}
|
}
|
||||||
else if ((this->writePtr < this->readPtr) && (endAtRead))
|
else if ((this->writePtr < this->readPtr) && (endAtRead))
|
||||||
{
|
{
|
||||||
|
// writers must not fall into a state of head parity, meaning that the entire buffer is readable
|
||||||
return (this->readPtr - this->writePtr) - 1;
|
return (this->readPtr - this->writePtr) - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto linearOverhead = length - (writePtr - base);
|
auto linearOverhead = this->length - (this->writePtr - this->base);
|
||||||
auto toWriteOverhead = readPtr - base;
|
auto toWriteOverhead = this->readPtr - this->base;
|
||||||
|
// writers must not fall into a state of head parity, meaning that the entire buffer is readable
|
||||||
return (linearOverhead + toWriteOverhead) - 1;
|
return (linearOverhead + toWriteOverhead) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,13 +254,17 @@ namespace Aurora::Memory
|
|||||||
pBase = this->readPtr;
|
pBase = this->readPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity:
|
||||||
|
|
||||||
if (pBase + uCount > this->base + this->length)
|
if (pBase + uCount > this->base + this->length)
|
||||||
{
|
{
|
||||||
|
this->flagReadError = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBase < this->base)
|
if (pBase < this->base)
|
||||||
{
|
{
|
||||||
|
this->flagReadError = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,13 +306,17 @@ namespace Aurora::Memory
|
|||||||
pBase = this->writePtr;
|
pBase = this->writePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity:
|
||||||
|
|
||||||
if (pBase + uCount > this->base + this->length)
|
if (pBase + uCount > this->base + this->length)
|
||||||
{
|
{
|
||||||
|
this->flagWriteError = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBase < this->base)
|
if (pBase < this->base)
|
||||||
{
|
{
|
||||||
|
this->flagWriteError = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user