[*] Hardening in the form of the prevention of future bad rewrites of similar code
[+] MemoryView::AtOffset [+] MemoryView::Take
This commit is contained in:
parent
951f9b73f3
commit
9c4315ff95
@ -648,28 +648,13 @@ namespace Aurora::Memory
|
||||
inline AuSPtr<MemoryViewWrite> ToSharedWriteView()
|
||||
{
|
||||
MemoryViewWrite view = *this;
|
||||
struct View : MemoryViewWrite
|
||||
{
|
||||
View(MemoryViewWrite &&in) : MemoryViewWrite(in)
|
||||
{ }
|
||||
|
||||
~View()
|
||||
{
|
||||
this->ResetControlBlock();
|
||||
AuResetMember(this->pin);
|
||||
}
|
||||
|
||||
AuSPtr<void> pin;
|
||||
};
|
||||
|
||||
if (!view)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto pView = AuMakeShared<View>(AuMove(view)))
|
||||
if (auto pView = AuMakeShared<MemoryViewWrite>(view.ptr, view.length, &this->uInUseCounter, AuSharedFromThis()))
|
||||
{
|
||||
pView->pin = AuSharedFromThis();
|
||||
return pView;
|
||||
}
|
||||
else
|
||||
@ -681,28 +666,13 @@ namespace Aurora::Memory
|
||||
inline AuSPtr<MemoryViewRead> ToSharedReadView()
|
||||
{
|
||||
MemoryViewRead view = *this;
|
||||
struct View : MemoryViewRead
|
||||
{
|
||||
View(MemoryViewRead &&in) : MemoryViewRead(in)
|
||||
{ }
|
||||
|
||||
~View()
|
||||
{
|
||||
this->ResetControlBlock();
|
||||
AuResetMember(this->pin);
|
||||
}
|
||||
|
||||
AuSPtr<void> pin;
|
||||
};
|
||||
|
||||
if (!view)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto pView = AuMakeShared<View>(AuMove(view)))
|
||||
if (auto pView = AuMakeShared<MemoryViewRead>(view.ptr, view.length, &this->uInUseCounter, AuSharedFromThis()))
|
||||
{
|
||||
pView->pin = AuSharedFromThis();
|
||||
return pView;
|
||||
}
|
||||
else
|
||||
|
@ -11,7 +11,21 @@ namespace Aurora::Memory
|
||||
{
|
||||
struct MemoryControlBlock
|
||||
{
|
||||
// Free-after-use mitigator: ensures a non-zero flag is kept whilst other memory views are present
|
||||
// This helps mitigate:
|
||||
// -> Take view from object
|
||||
// -> Make view shared
|
||||
// -> Pass off shared view to another subsystem
|
||||
// -> Use the aforementioned object to resize, release, or do something bad with the memory pointed to by the initial view
|
||||
// Mitgation: SysAssert(!pObject->uInUse)
|
||||
AuAUInt32 *pInUseCounter {};
|
||||
|
||||
// Mitigation (cont) and reducing code reuse:
|
||||
// -> Allow for [shared!] memory views to have a shared freestanding owner
|
||||
// -> Ensure reference counters or other forms of memory management don't free the owner before us
|
||||
// (Consider inverse construction order, for instance, we'd have to always call MemoryView::ResetControlBlock()
|
||||
// in a derived subclass, in order release the pInUseCounter reference before the derived shared members get released)
|
||||
AuSPtr<void> pPinner; // WARNING: as usual, std types don't validate their allocator, and our shared ptrs can be different between binaries!
|
||||
};
|
||||
|
||||
template<bool Readonly_b>
|
||||
@ -62,6 +76,7 @@ namespace Aurora::Memory
|
||||
{
|
||||
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
|
||||
}
|
||||
this->controlBlock.pPinner = view.controlBlock.pPinner;
|
||||
}
|
||||
|
||||
MemoryView(MemoryView &&view)
|
||||
@ -69,38 +84,10 @@ namespace Aurora::Memory
|
||||
this->ptr = view.ptr;
|
||||
this->length = view.length;
|
||||
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
|
||||
this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner);
|
||||
view.controlBlock.pInUseCounter = nullptr;
|
||||
}
|
||||
|
||||
~MemoryView()
|
||||
{
|
||||
if (controlBlock.pInUseCounter)
|
||||
{
|
||||
AuAtomicSub(controlBlock.pInUseCounter, 1u);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryView &operator =(MemoryView &&view)
|
||||
{
|
||||
this->ptr = view.ptr;
|
||||
this->length = view.length;
|
||||
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
|
||||
view.controlBlock.pInUseCounter = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MemoryView &operator =(const MemoryView &view)
|
||||
{
|
||||
this->ptr = view.ptr;
|
||||
this->length = view.length;
|
||||
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
|
||||
if (this->controlBlock.pInUseCounter)
|
||||
{
|
||||
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, int Z>
|
||||
constexpr MemoryView(T(&a)[Z])
|
||||
{
|
||||
@ -139,6 +126,24 @@ namespace Aurora::Memory
|
||||
AuAtomicAdd(pInUseCounter, 1u);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr MemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr<void> &pRAIIOwner)
|
||||
{
|
||||
this->ptr = start;
|
||||
if constexpr (AuIsSame_v<T, Void_t>)
|
||||
{
|
||||
this->length = reinterpret_cast<const AuUInt8 *>(end) - reinterpret_cast<const AuUInt8 *>(start);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->length = (end - start) * sizeof(T);
|
||||
}
|
||||
|
||||
this->controlBlock.pInUseCounter = pInUseCounter;
|
||||
AuAtomicAdd(pInUseCounter, 1u);
|
||||
this->controlBlock.pPinner = pRAIIOwner;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr MemoryView(T *start, AuUInt length) // WARNING: length != count
|
||||
// where T = whogivesafuck
|
||||
@ -156,6 +161,58 @@ namespace Aurora::Memory
|
||||
AuAtomicAdd(pInUseCounter, 1u);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr MemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr<void> &pRAIIOwner) // WARNING: length != count
|
||||
{
|
||||
this->ptr = start;
|
||||
this->length = length;
|
||||
this->controlBlock.pInUseCounter = pInUseCounter;
|
||||
AuAtomicAdd(pInUseCounter, 1u);
|
||||
this->controlBlock.pPinner = pRAIIOwner;
|
||||
}
|
||||
|
||||
~MemoryView()
|
||||
{
|
||||
this->ResetControlBlock();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
MemoryView(T *start, AuUInt length, const MemoryControlBlock ©Block)
|
||||
{
|
||||
this->ptr = start;
|
||||
this->length = length;
|
||||
this->controlBlock = copyBlock;
|
||||
if (this->controlBlock.pInUseCounter)
|
||||
{
|
||||
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
|
||||
}
|
||||
}
|
||||
public:
|
||||
|
||||
MemoryView &operator =(MemoryView &&view)
|
||||
{
|
||||
this->ptr = view.ptr;
|
||||
this->length = view.length;
|
||||
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
|
||||
view.controlBlock.pInUseCounter = nullptr;
|
||||
this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MemoryView &operator =(const MemoryView &view)
|
||||
{
|
||||
this->ptr = view.ptr;
|
||||
this->length = view.length;
|
||||
this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter;
|
||||
if (this->controlBlock.pInUseCounter)
|
||||
{
|
||||
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
|
||||
}
|
||||
this->controlBlock.pPinner = view.controlBlock.pPinner;
|
||||
return *this;
|
||||
}
|
||||
|
||||
AuUInt ToPointerValue() const
|
||||
{
|
||||
return reinterpret_cast<const AuUInt>(this->ptr);
|
||||
@ -191,7 +248,7 @@ namespace Aurora::Memory
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return HasMemory();
|
||||
return this->HasMemory();
|
||||
}
|
||||
|
||||
U8_t ToPointer() const
|
||||
@ -219,8 +276,41 @@ namespace Aurora::Memory
|
||||
return reinterpret_cast<U8_t>(this->ptr) + this->length;
|
||||
}
|
||||
|
||||
MemoryView AtOffset(AuUInt uOffset)
|
||||
{
|
||||
if (uOffset < this->uLength)
|
||||
{
|
||||
return MemoryView(this->pBase + uOffset, this->uLength - uOffset, this->controlBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
MemoryView Take(AuUInt uLength)
|
||||
{
|
||||
if (uLength <= this->uLength)
|
||||
{
|
||||
return MemoryView(this->pBase, uLength, this->controlBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
Void_t /*const*/ ptr;
|
||||
Void_t /*const*/ pBase;
|
||||
};
|
||||
union
|
||||
{
|
||||
AuUInt /*const*/ length;
|
||||
AuUInt /*const*/ uLength;
|
||||
};
|
||||
|
||||
private:
|
||||
MemoryControlBlock controlBlock;
|
||||
|
||||
@ -231,6 +321,8 @@ namespace Aurora::Memory
|
||||
{
|
||||
AuAtomicSub(pCounter, 1u);
|
||||
}
|
||||
|
||||
AuResetMember(this->controlBlock.pPinner);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user