Try merging free image lists if failed to allocate one

This commit is contained in:
Ted John 2016-10-02 01:10:43 +01:00
parent ff34967e9b
commit 305e6184f8
1 changed files with 70 additions and 10 deletions

View File

@ -72,21 +72,57 @@ static bool AllocatedListRemove(uint32 baseImageId, uint32 count)
}
#endif
static uint32 AllocateImageList(uint32 count)
static uint32 GetNumFreeImagesRemaining()
{
Guard::Assert(count != 0, GUARD_LINE);
return MAX_IMAGES - _allocatedImageCount;
}
if (!_initialised)
{
_initialised = true;
_freeLists.clear();
_freeLists.push_back({ BASE_IMAGE_ID, MAX_IMAGES });
static void InitialiseImageList()
{
Guard::Assert(!_initialised, GUARD_LINE);
_freeLists.clear();
_freeLists.push_back({ BASE_IMAGE_ID, MAX_IMAGES });
#ifdef DEBUG
_allocatedLists.clear();
_allocatedLists.clear();
#endif
_allocatedImageCount = 0;
}
_allocatedImageCount = 0;
_initialised = true;
}
/**
* Merges all the free lists into one, a process of defragmentation.
*/
static void MergeFreeLists()
{
_freeLists.sort(
[](const ImageList &a, const ImageList &b) -> bool
{
return a.BaseId < b.BaseId;
});
for (auto it = _freeLists.begin(); it != _freeLists.end(); it++)
{
bool mergeHappened;
do
{
mergeHappened = false;
auto nextIt = std::next(it);
if (nextIt != _freeLists.end())
{
if (it->BaseId + it->Count == nextIt->BaseId)
{
// Merge next list into this list
it->Count += nextIt->Count;
_freeLists.erase(nextIt);
mergeHappened = true;
}
}
} while (mergeHappened);
}
}
static uint32 TryAllocateImageList(uint32 count)
{
for (auto it = _freeLists.begin(); it != _freeLists.end(); it++)
{
ImageList imageList = *it;
@ -110,6 +146,30 @@ static uint32 AllocateImageList(uint32 count)
return INVALID_IMAGE_ID;
}
static uint32 AllocateImageList(uint32 count)
{
Guard::Assert(count != 0, GUARD_LINE);
if (!_initialised)
{
InitialiseImageList();
}
uint32 baseImageId = INVALID_IMAGE_ID;
uint32 freeImagesRemaining = GetNumFreeImagesRemaining();
if (freeImagesRemaining >= count)
{
baseImageId = TryAllocateImageList(count);
if (baseImageId == INVALID_IMAGE_ID)
{
// Defragment and try again
MergeFreeLists();
baseImageId = TryAllocateImageList(count);
}
}
return baseImageId;
}
static void FreeImageList(uint32 baseImageId, uint32 count)
{
Guard::Assert(_initialised, GUARD_LINE);