You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
656 lines
26 KiB
C++
656 lines
26 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
|
|
#ifndef CRYINCLUDE_CRYPOOL_CONTAINER_H
|
|
#define CRYINCLUDE_CRYPOOL_CONTAINER_H
|
|
#pragma once
|
|
|
|
|
|
namespace NCryPoolAlloc
|
|
{
|
|
template<size_t TElementCount, class TElement>
|
|
class CPool
|
|
: public CMemoryStatic<TElementCount* sizeof(TElement)>
|
|
{
|
|
class CPoolNode;
|
|
class CPoolNode
|
|
: public CListItem<CPoolNode>
|
|
{
|
|
};
|
|
CList<CPoolNode> m_List;
|
|
public:
|
|
ILINE CPool()
|
|
{
|
|
CPoolNode* pPrev = 0;
|
|
CPoolNode* pNode = 0;
|
|
for (size_t a = 1; a < TElementCount; a++) //skip first element as it would be counted as zero ptr
|
|
{
|
|
uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[a * sizeof(TElement)];
|
|
pNode = reinterpret_cast<CPoolNode*>(pData);
|
|
pNode->Prev(pPrev);
|
|
if (pPrev)
|
|
{
|
|
pPrev->Next(pNode);
|
|
}
|
|
else
|
|
{
|
|
m_List.First(pNode);
|
|
}
|
|
pPrev = pNode;
|
|
// m_List.AddLast(pNode);
|
|
}
|
|
if (pPrev)
|
|
{
|
|
pPrev->Next(0);
|
|
m_List.Last(pPrev);
|
|
}
|
|
}
|
|
ILINE uint8* Allocate([[maybe_unused]] size_t Size, [[maybe_unused]] size_t Align = 1)
|
|
{
|
|
CPoolNode* pNode = m_List.PopFirst();
|
|
return reinterpret_cast<uint8*>(pNode);
|
|
}
|
|
|
|
template<class T>
|
|
ILINE void Free(T* pData)
|
|
{
|
|
if (pData)
|
|
{
|
|
CPoolNode* pNode = reinterpret_cast<CPoolNode*>(pData);
|
|
m_List.AddLast(pNode);
|
|
}
|
|
}
|
|
|
|
ILINE TElement& operator[](uint32 Idx)
|
|
{
|
|
uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[Idx * sizeof(TElement)];
|
|
return *reinterpret_cast<TElement*>(pData);
|
|
}
|
|
|
|
ILINE const TElement& operator[](uint32 Idx) const
|
|
{
|
|
const uint8* pData = &CMemoryStatic<TElementCount* sizeof(TElement)>::Data()[Idx * sizeof(TElement)];
|
|
return *reinterpret_cast<const TElement*>(pData);
|
|
}
|
|
};
|
|
|
|
template<class TMemory, bool BoundsCheck = false>
|
|
class CInPlace
|
|
: public TMemory
|
|
{
|
|
protected:
|
|
CList<CListItemInPlace> m_Items;
|
|
size_t m_Allocated;
|
|
CListItemInPlace* m_pEmpty;
|
|
|
|
|
|
ILINE void AllocatedMemory(size_t S)
|
|
{
|
|
m_Allocated += S + sizeof(CListItemInPlace);
|
|
}
|
|
ILINE void FreedMemory(size_t S)
|
|
{
|
|
m_Allocated -= S + sizeof(CListItemInPlace);
|
|
}
|
|
ILINE void Stack(CListItemInPlace* pItem)
|
|
{
|
|
}
|
|
public:
|
|
ILINE CInPlace()
|
|
: m_Allocated(0)
|
|
{
|
|
}
|
|
|
|
ILINE void InitMem(const size_t S = 0, uint8* pData = 0)
|
|
{
|
|
TMemory::InitMem(S, pData);
|
|
if (!TMemory::MemSize())
|
|
{
|
|
return;
|
|
}
|
|
pData = TMemory::Data();
|
|
CListItemInPlace* pFirst = reinterpret_cast<CListItemInPlace*>(pData);
|
|
CListItemInPlace* pFree = pFirst + 1;
|
|
CListItemInPlace* pLast = reinterpret_cast<CListItemInPlace*>(pData + TMemory::MemSize()) - 1;
|
|
m_Items.~CList<CListItemInPlace>();
|
|
new (&m_Items)CList<CListItemInPlace>();
|
|
m_Items.AddLast(pFirst);
|
|
m_Items.AddLast(pFree);
|
|
m_Items.AddLast(pLast);
|
|
|
|
pFirst->InUse(0); //static first item
|
|
pFree->Free();
|
|
pLast->InUse(0); //static last item
|
|
m_pEmpty = pFree;
|
|
m_Allocated = 0;
|
|
}
|
|
|
|
ILINE size_t FragmentCount() const
|
|
{
|
|
return m_Items.Count();
|
|
}
|
|
|
|
ILINE CListItemInPlace* Split(CListItemInPlace* pItem, size_t Size, size_t Align)
|
|
{
|
|
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
|
|
Offset += pItem->MemSize(); //ptr to end
|
|
Offset -= Size; //minus size
|
|
Size += Offset & (Align - 1); //adjust size to fit required alignment
|
|
Offset -= Offset & (Align - 1);
|
|
size_t TSize = sizeof(CListItemInPlace);
|
|
Offset -= TSize; //header
|
|
|
|
if (Offset <= reinterpret_cast<size_t>(pItem + 1)) //not enough space for splitting?
|
|
{
|
|
return pItem;
|
|
}
|
|
|
|
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
|
|
|
|
const size_t Offset2 = reinterpret_cast<size_t>(pItemNext->Data());
|
|
CPA_ASSERT(!(Offset2 & (Align - 1)));
|
|
m_Items.AddBehind(pItemNext, pItem);
|
|
//pItemNext->Prev(pItem);
|
|
//pItemNext->Next(pItem->Next());
|
|
|
|
// if(pItem->Next())
|
|
// pItem->Next()->Prev(pItemNext);
|
|
|
|
// pItem->Next(pItemNext);
|
|
pItemNext->Free();
|
|
return pItemNext;
|
|
}
|
|
|
|
ILINE void Merge(CListItemInPlace* pItem)
|
|
{
|
|
//merge with next if possible
|
|
CListItemInPlace* pItemNext = pItem->Next();
|
|
if (pItemNext->IsFree())
|
|
{
|
|
if (m_pEmpty == pItemNext)
|
|
{
|
|
m_pEmpty = pItem;
|
|
}
|
|
m_Items.Remove(pItemNext);
|
|
//pItem->Next(pItemNext->Next());
|
|
//pItem->Next()->Prev(pItem);
|
|
}
|
|
//merge with prev if possible
|
|
CListItemInPlace* pItemPrev = pItem->Prev();
|
|
if (pItemPrev->IsFree())
|
|
{
|
|
if (m_pEmpty == pItem)
|
|
{
|
|
m_pEmpty = pItemPrev;
|
|
}
|
|
m_Items.Remove(pItem);
|
|
//pItemPrev->Next(pItem->Next());
|
|
//pItem->Next()->Prev(pItemPrev);
|
|
pItem = pItemPrev;
|
|
}
|
|
}
|
|
template<class T>
|
|
ILINE T Resolve(void* rItem) const
|
|
{
|
|
return reinterpret_cast<T>(rItem);
|
|
}
|
|
|
|
template<class T>
|
|
ILINE size_t Size(const T* pData) const
|
|
{
|
|
const CListItemInPlace* pItem = Item(pData);
|
|
return pItem->MemSize();
|
|
}
|
|
|
|
bool InBounds(const void* pData, const bool Check) const
|
|
{
|
|
return !Check || (
|
|
reinterpret_cast<size_t>(pData) >= reinterpret_cast<size_t>(TMemory::Data()) &&
|
|
reinterpret_cast<size_t>(pData) < reinterpret_cast<size_t>(TMemory::Data()) + TMemory::MemSize());
|
|
}
|
|
|
|
template<class T>
|
|
ILINE bool Free(T* pData, bool ForceBoundsCheck = false)
|
|
{
|
|
if (pData && InBounds(pData, BoundsCheck | ForceBoundsCheck))
|
|
{
|
|
CListItemInPlace* pItem = Item(pData);
|
|
FreedMemory(pItem->MemSize());
|
|
pItem->Free();
|
|
Merge(pItem);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ILINE bool Beat(){return false; }//dummy beat in case no defragmentator is wraping
|
|
ILINE size_t MemFree() const{return TMemory::MemSize() - m_Allocated; }
|
|
ILINE size_t MemSize() const{return TMemory::MemSize(); }
|
|
|
|
ILINE uint8* Handle(CListItemInPlace* pItem) const
|
|
{
|
|
return pItem->Data();
|
|
}
|
|
template<class T>
|
|
ILINE CListItemInPlace* Item(T* pData)
|
|
{
|
|
return reinterpret_cast<CListItemInPlace*>(pData) - 1;
|
|
}
|
|
template<class T>
|
|
ILINE const CListItemInPlace* Item(const T* pData) const
|
|
{
|
|
return reinterpret_cast<const CListItemInPlace*>(pData) - 1;
|
|
}
|
|
ILINE static bool Defragmentable(){return false; }
|
|
|
|
template<class T>
|
|
ILINE bool ReSize(T* pData, size_t SizeNew)
|
|
{
|
|
//special cases
|
|
CListItemInPlace* pItem = Item(*pData);
|
|
const size_t SizeOld = pItem->MemSize();
|
|
|
|
//reduction
|
|
if (SizeOld > SizeNew)
|
|
{
|
|
if (pItem->Next()->IsFree())
|
|
{
|
|
CListItemInPlace* pNextNext = pItem->Next()->Next();
|
|
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
|
|
Offset += SizeNew; //Offset to next
|
|
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
|
|
pItem->Next(pItemNext);
|
|
pNextNext->Prev(pItemNext);
|
|
pItemNext->Prev(pItem);
|
|
pItemNext->Next(pNextNext);
|
|
pItemNext->Free();
|
|
return true;
|
|
}
|
|
|
|
if (SizeOld - SizeNew <= sizeof(CListItemInPlace))
|
|
{
|
|
return true; //header is bigger than the amount of freed memory
|
|
}
|
|
//split
|
|
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
|
|
Offset += SizeNew; //Offset to next
|
|
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
|
|
m_Items.AddBehind(pItemNext, pItem);
|
|
pItemNext->Free();
|
|
return true;
|
|
}
|
|
|
|
//SizeOld<SizeNew grow
|
|
CListItemInPlace* pNext = pItem->Next();
|
|
CListItemInPlace* pNextNext = pNext->Next();
|
|
const size_t SizeNext = pNext->IsFree() ? pNext->MemSize() + sizeof(CListItemInPlace) : 0;
|
|
if (SizeNew <= SizeNext + SizeOld)
|
|
{
|
|
if (SizeNew + sizeof(CListItemInPlace) + 1 < SizeNext + SizeOld)
|
|
{
|
|
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
|
|
Offset += SizeNew; //Offset to next
|
|
CListItemInPlace* pItemNext = reinterpret_cast<CListItemInPlace*>(Offset);
|
|
pItem->Next(pItemNext);
|
|
pNextNext->Prev(pItemNext);
|
|
pItemNext->Prev(pItem);
|
|
pItemNext->Next(pNextNext);
|
|
pItemNext->Free();
|
|
}
|
|
else
|
|
{
|
|
pItem->Next(pNextNext);
|
|
pNextNext->Prev(pItem);
|
|
}
|
|
return true;
|
|
}
|
|
return false; //no further in-place realloc possible
|
|
}
|
|
};
|
|
|
|
template<class TMemory, size_t TNodeCount, bool BoundsCheck = false>
|
|
class CReferenced
|
|
: public TMemory
|
|
{
|
|
typedef CPool<TNodeCount, CListItemReference> tdNodePool;
|
|
|
|
protected:
|
|
tdNodePool m_NodePool;
|
|
CList<CListItemReference> m_Items;
|
|
size_t m_Allocated;
|
|
CListItemReference* m_pEmpty;
|
|
|
|
ILINE void AllocatedMemory(size_t S)
|
|
{
|
|
m_Allocated += S;
|
|
}
|
|
ILINE void FreedMemory(size_t S)
|
|
{
|
|
m_Allocated -= S;
|
|
}
|
|
ILINE void Stack(CListItemReference* pItem)
|
|
{
|
|
m_Items.Validate(pItem);
|
|
CListItemReference* pItem2 = 0;
|
|
CListItemReference* pNext = pItem->Next();
|
|
uint8* pData = pItem->Data(pNext->Align());
|
|
if (pData != pItem->Data()) //needs splitting 'cause of alignment?
|
|
{
|
|
pItem2 = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
if (!pItem2) //no free node found for splitting?
|
|
{
|
|
return; //failed to stack -> return
|
|
}
|
|
}
|
|
|
|
memmove(pData, pNext->Data(), pNext->MemSize());
|
|
|
|
if (pItem2) //was not aligned?
|
|
{
|
|
//then keep the current ITem
|
|
const size_t SizeItem = pItem->MemSize();
|
|
const size_t SizeNext = pNext->MemSize();
|
|
m_Items.AddBehind(pItem2, pNext);
|
|
pItem2->Data(pData + SizeNext);
|
|
pNext->Data(pData);
|
|
pItem2->MemSize(pItem2->Next()->Data() - pItem2->Data());
|
|
pNext->MemSize(SizeNext);
|
|
pItem->MemSize(pNext->Data() - pItem->Data());
|
|
m_Items.Validate(pItem);
|
|
m_Items.Validate(pItem2);
|
|
m_Items.Validate(pNext);
|
|
}
|
|
else
|
|
{
|
|
const size_t SizeItem = pItem->MemSize();
|
|
const size_t SizeNext = pNext->MemSize();
|
|
m_Items.Remove(pItem);
|
|
m_Items.AddBehind(pItem, pNext);
|
|
pItem->Data(pNext->Data());
|
|
pNext->Data(pData);
|
|
pNext->MemSize(SizeItem);
|
|
pItem->MemSize(SizeNext);
|
|
m_Items.Validate(pItem);
|
|
m_Items.Validate(pNext);
|
|
}
|
|
}
|
|
public:
|
|
ILINE CReferenced()
|
|
: m_Allocated(0)
|
|
{
|
|
}
|
|
|
|
ILINE void InitMem(const size_t S = 0, uint8* pData = 0)
|
|
{
|
|
TMemory::InitMem(S, pData);
|
|
if (!TMemory::MemSize())
|
|
{
|
|
return;
|
|
}
|
|
pData = TMemory::Data();
|
|
CListItemReference* pItem = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
CListItemReference* pLast = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
m_Items.AddFirst(pItem);
|
|
m_Items.AddLast(pLast);
|
|
pLast->Init(pData + TMemory::MemSize(), 0, pItem, 0);
|
|
pLast->InUse(0);
|
|
pItem->Init(pData, TMemory::MemSize(), 0, pLast);
|
|
pItem->Free();
|
|
m_pEmpty = pItem;
|
|
m_Allocated = 0;
|
|
}
|
|
|
|
ILINE size_t FragmentCount() const
|
|
{
|
|
return m_Items.Count();
|
|
}
|
|
|
|
ILINE CListItemReference* Split(CListItemReference* pItem, size_t Size, size_t Align)
|
|
{
|
|
size_t Offset = reinterpret_cast<size_t>(pItem->Data());
|
|
if (!(Offset & (Align - 1))) //perfectly aligned?
|
|
{
|
|
if (pItem->MemSize() != Size) //not perfectly fitting?
|
|
{ //then split
|
|
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
if (!pItemPrev)
|
|
{
|
|
return 0;
|
|
}
|
|
const size_t OrgSize = pItem->MemSize();
|
|
m_Items.AddBefore(pItemPrev, pItem);
|
|
pItemPrev->Data(pItem->Data());
|
|
pItem->Data(pItem->Data() + Size);
|
|
pItem->MemSize(OrgSize - Size);
|
|
pItemPrev->MemSize(Size);
|
|
pItem = pItemPrev;
|
|
}
|
|
return pItem;
|
|
}
|
|
|
|
//not aligned to block start
|
|
//then lets try to align to block end
|
|
Offset += pItem->MemSize(); //ptr to end
|
|
Offset -= Size; //minus size
|
|
if (!(Offset & (Align - 1))) //perfectly aligned?
|
|
{
|
|
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
if (!pItemPrev)
|
|
{
|
|
return 0;
|
|
}
|
|
const size_t OrgSize = pItem->MemSize();
|
|
m_Items.AddBefore(pItemPrev, pItem);
|
|
pItemPrev->Data(pItem->Data());
|
|
pItem->Data(reinterpret_cast<uint8*>(Offset));
|
|
pItemPrev->MemSize(OrgSize - Size);
|
|
pItem->MemSize(Size);
|
|
pItemPrev->Free();
|
|
return pItem;
|
|
}
|
|
//last resort, fragment it into 3 parts
|
|
|
|
//Size +=Offset&(Align-1); //adjust size to fit required alignment
|
|
Offset -= Offset & (Align - 1);
|
|
|
|
CListItemReference* pItemPrev = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
CListItemReference* pItemNext = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
if (!pItemPrev || !pItemNext)
|
|
{
|
|
return 0;
|
|
}
|
|
const size_t OrgSize = pItem->MemSize();
|
|
|
|
m_Items.AddBefore(pItemPrev, pItem);
|
|
m_Items.AddBehind(pItemNext, pItem);
|
|
|
|
pItemPrev->Data(pItem->Data());
|
|
pItem->Data(reinterpret_cast<uint8*>(Offset));
|
|
pItemNext->Data(pItem->Data() + Size);
|
|
pItemPrev->MemSize(pItem->Data() - pItemPrev->Data());
|
|
pItemNext->MemSize(OrgSize - pItemPrev->MemSize() - Size);
|
|
pItem->MemSize(Size);
|
|
|
|
pItemPrev->Free();
|
|
pItemNext->Free();
|
|
return pItem;
|
|
}
|
|
|
|
ILINE void Merge(CListItemReference* pItem)
|
|
{
|
|
m_Items.Validate(pItem);
|
|
|
|
//merge with next if possible
|
|
CListItemReference* pItemNext = pItem->Next();
|
|
if (pItemNext && pItemNext->IsFree())
|
|
{
|
|
if (m_pEmpty == pItemNext)
|
|
{
|
|
m_pEmpty = pItem;
|
|
}
|
|
const size_t OrgSize = pItem->MemSize();
|
|
const size_t NextSize = pItemNext->MemSize();
|
|
m_Items.Remove(pItemNext);
|
|
pItem->MemSize(OrgSize + NextSize);
|
|
m_NodePool.Free(pItemNext);
|
|
}
|
|
//merge with prev if possible
|
|
CListItemReference* pItemPrev = pItem->Prev();
|
|
if (pItemPrev && pItemPrev->IsFree())
|
|
{
|
|
if (m_pEmpty == pItem)
|
|
{
|
|
m_pEmpty = pItemPrev;
|
|
}
|
|
const size_t OrgSize = pItem->MemSize();
|
|
const size_t PrevSize = pItemPrev->MemSize();
|
|
m_Items.Remove(pItem);
|
|
pItemPrev->MemSize(PrevSize + OrgSize);
|
|
m_NodePool.Free(pItem);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
ILINE T Resolve(const uint32 ID)
|
|
{
|
|
CPA_ASSERT(ID); //0 is invalid
|
|
return reinterpret_cast<T>(Item(ID)->Data());
|
|
}
|
|
|
|
ILINE uint32 AddressToHandle(void* pData)
|
|
{
|
|
for (CListItemReference* pItem = m_Items.First(); pItem; pItem = pItem->Next())
|
|
{
|
|
if (pItem->Data() == pData)
|
|
{
|
|
return Handle(pItem);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template<class T>
|
|
ILINE size_t Size(T ID) const
|
|
{
|
|
CPA_ASSERT(ID); //0 is invalid
|
|
return Item(ID)->MemSize();
|
|
}
|
|
template<class T>
|
|
bool InBounds([[maybe_unused]] T ID, [[maybe_unused]] const bool Check) const
|
|
{
|
|
//boundscheck doesn't work for Referenced containers
|
|
return true;
|
|
}
|
|
|
|
template<class T>
|
|
ILINE bool Free(T ID, bool ForceBoundsCheck = false)
|
|
{
|
|
IF (!ID, false)
|
|
{
|
|
return true;
|
|
}
|
|
IF (!InBounds(ID, BoundsCheck | ForceBoundsCheck), false)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CListItemReference* pItem = Item(ID);
|
|
FreedMemory(pItem->MemSize());
|
|
pItem->Free();
|
|
Merge(pItem);
|
|
return true;
|
|
}
|
|
|
|
ILINE bool Beat(){return false; }//dummy beat in case no defragmentator is wraping
|
|
|
|
ILINE size_t MemFree() const{return TMemory::MemSize() - m_Allocated; }
|
|
|
|
ILINE size_t MemSize() const{return TMemory::MemSize(); }
|
|
|
|
ILINE uint32 Handle(CListItemReference* pItem) const
|
|
{
|
|
return static_cast<uint32>(pItem - &m_NodePool[0]);
|
|
}
|
|
ILINE CListItemReference* Item(uint32 ID)
|
|
{
|
|
return &m_NodePool[ID];
|
|
}
|
|
ILINE const CListItemReference* Item(uint32 ID) const
|
|
{
|
|
return &m_NodePool[ID];
|
|
}
|
|
ILINE static bool Defragmentable(){return true; }
|
|
|
|
|
|
|
|
template<class T>
|
|
ILINE bool ReSize(T* pData, size_t SizeNew)
|
|
{
|
|
CListItemReference* pItem = Item(*pData);
|
|
const size_t SizeOld = pItem->MemSize();
|
|
|
|
//reduction
|
|
if (SizeOld > SizeNew)
|
|
{
|
|
if (pItem->Next()->IsFree())
|
|
{
|
|
CListItemReference* pNext = pItem->Next();
|
|
const size_t NextSize = pNext->MemSize();
|
|
pNext->Data(pNext->Data() + SizeNew - SizeOld);
|
|
pNext->MemSize(NextSize - SizeNew + SizeOld);
|
|
pItem->MemSize(SizeNew);
|
|
return true;
|
|
}
|
|
|
|
//split
|
|
CListItemReference* pItemNext = reinterpret_cast<CListItemReference*>(m_NodePool.Allocate(1, 1));
|
|
m_Items.AddBehind(pItemNext, pItem);
|
|
pItemNext->Data(pItem->Data() + SizeNew);
|
|
pItem->MemSize(SizeNew);
|
|
pItemNext->MemSize(SizeOld - SizeNew);
|
|
pItemNext->Free();
|
|
return true;
|
|
}
|
|
|
|
//SizeOld<SizeNew grow
|
|
CListItemReference* pNext = pItem->Next();
|
|
const size_t SizeNext = pNext->IsFree() ? pNext->MemSize() : 0;
|
|
if (SizeNew <= SizeNext + SizeOld)
|
|
{
|
|
if (SizeNew == SizeNext + SizeOld)
|
|
{
|
|
m_Items.Remove(pNext);
|
|
m_NodePool.Free(pNext);
|
|
}
|
|
else
|
|
{
|
|
pNext->Data(pNext->Data() + SizeNew - SizeOld);
|
|
pNext->MemSize(SizeNext - SizeNew + SizeOld);
|
|
}
|
|
pItem->MemSize(SizeNew);
|
|
return true;
|
|
}
|
|
return false; //no further in-place realloc possible
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // CRYINCLUDE_CRYPOOL_CONTAINER_H
|
|
|