Skip to content

Commit 9bf6559

Browse files
committed
added Deallocate function
1 parent 5bf417f commit 9bf6559

File tree

1 file changed

+162
-86
lines changed

1 file changed

+162
-86
lines changed

tests/src/resources/test_ResourceSystem.cpp

Lines changed: 162 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -697,16 +697,28 @@ class Allocator
697697
return ptr;
698698
}
699699

700-
// void Deallocate(void* ptr)
701-
// {
702-
// if (!ptr) return;
703-
//
704-
// BlockHeader* header = TO_HBLOCK((TO_BYTES(ptr) - sizeof(BlockHeader)));
705-
// size_t blockSize = GetHeaderSize(header);
706-
//
707-
// TryCoalesce(header, blockSize);
708-
// }
709-
//
700+
template<typename T>
701+
void Deallocate(T*& ptr)
702+
{
703+
if (!ptr) return;
704+
705+
BlockHeader* header = TO_HBLOCK((TO_BYTES(ptr) - sizeof(BlockHeader)));
706+
size_t blockSize = GetHeaderSize(header);
707+
708+
size_t totalBlockSize = blockSize;
709+
BlockHeader* targetHeader = TryCoalesce(header, totalBlockSize);
710+
BlockFooter* footer = TO_FBLOCK((TO_BYTES(targetHeader) + totalBlockSize - sizeof(BlockFooter)));
711+
712+
targetHeader->sizeAndFlags = (totalBlockSize << FLAG_BITS) | (targetHeader->sizeAndFlags & IS_PREV_FREE_FLAG) | IS_FREE_FLAG;
713+
footer->totalBlockSize = totalBlockSize;
714+
715+
BlockHeader* nextHeader = GetNextHeader(targetHeader, totalBlockSize);
716+
if (nextHeader) nextHeader->sizeAndFlags |= IS_PREV_FREE_FLAG;
717+
718+
CreateNewBlock(TO_BYTES(targetHeader), totalBlockSize);
719+
ptr = nullptr;
720+
}
721+
710722
size_t GetNextFreeSlotIndex(OUT size_t& fl,OUT size_t& sl)
711723
{
712724
sl = FindLargerSlots(slBitmasks[fl], sl);
@@ -734,35 +746,34 @@ class Allocator
734746
const size_t SetBitOn(size_t val, size_t bit) { return val | BitMask(bit);}
735747
const size_t FlipBits(size_t mask) { return ~(mask); }
736748
const size_t Mask(size_t value, size_t mask) { return value & mask; }
737-
//
749+
738750
const size_t GetHeaderSize(BlockHeader* header) { return header->sizeAndFlags >> FLAG_BITS; }
739751
const size_t PrevBlockIsFree(BlockHeader* header) { return Mask(header->sizeAndFlags, IS_PREV_FREE_FLAG); }
740752
const size_t BlockIsFree(BlockHeader* header) { return Mask(header->sizeAndFlags, IS_FREE_FLAG); }
741753
BlockHeader* GetHeader(FreeBlockNode* node) { return TO_HBLOCK((TO_BYTES(node) - sizeof(BlockHeader))); }
742-
//
743-
// BlockHeader* TryCoalesce(BlockHeader* header, OUT size_t& size)
744-
// {
745-
// BlockHeader* start = header;
746-
// BlockHeader* prev = GetPreviousHeader(header);
747-
//
748-
// if (prev && PrevBlockIsFree(header))
749-
// {
750-
// start = prev;
751-
// size += GetHeaderSize(prev);
752-
// RemoveFromFreeList(prev);
753-
// }
754-
//
755-
// BlockHeader* next = GetNextHeader(header, GetHeaderSize(header));
756-
//
757-
// if (next && BlockIsFree(next))
758-
// {
759-
// size += GetHeaderSize(next);
760-
// RemoveFromFreeList(next);
761-
// }
762-
//
763-
// start->sizeAndFlags = (size << FLAG_BITS) | IS_FREE_FLAG;
764-
// CreateNewBlock(TO_BYTES(start), size);
765-
// }
754+
755+
BlockHeader* TryCoalesce(BlockHeader* header, OUT size_t& size)
756+
{
757+
BlockHeader* start = header;
758+
BlockHeader* prev = GetPreviousHeader(header);
759+
760+
if (prev && BlockIsFree(prev))
761+
{
762+
start = prev;
763+
size += GetHeaderSize(prev);
764+
RemoveFromFreeList(prev);
765+
}
766+
767+
BlockHeader* next = GetNextHeader(start, size);
768+
769+
if (next && BlockIsFree(next))
770+
{
771+
size += GetHeaderSize(next);
772+
RemoveFromFreeList(next);
773+
}
774+
775+
return start;
776+
}
766777

767778
BlockHeader* GetPreviousHeader(void* currentHeader)
768779
{
@@ -772,19 +783,19 @@ class Allocator
772783
return prevHeader;
773784
}
774785

775-
// BlockHeader* GetNextHeader(void* currentHeader, size_t offset)
776-
// {
777-
// unsigned char* next = TO_BYTES(currentHeader) + offset;
778-
// if (next >= (data+capacity)) return nullptr;
779-
// if (IsTail(next)) return nullptr;
780-
// return TO_HBLOCK(next);
781-
// }
786+
BlockHeader* GetNextHeader(void* currentHeader, size_t offset)
787+
{
788+
unsigned char* next = TO_BYTES(currentHeader) + offset;
789+
if (next >= (data+capacity)) return nullptr;
790+
if (IsTail(next)) return nullptr;
791+
return TO_HBLOCK(next);
792+
}
782793

783794
void TrySetPreviousHeaderFlag(void* currentHeader, size_t& flags)
784795
{
785796
BlockHeader* prevHeader = GetPreviousHeader(currentHeader);
786797
if (prevHeader &&
787-
!Mask(prevHeader->sizeAndFlags,IS_FREE_FLAG)) flags |= IS_PREV_FREE_FLAG;
798+
Mask(prevHeader->sizeAndFlags,IS_FREE_FLAG)) flags |= IS_PREV_FREE_FLAG;
788799
}
789800

790801
void TrySplitBlock(BlockHeader* header, FreeBlockNode* block, size_t size, size_t fl, size_t sl, size_t index)
@@ -807,14 +818,16 @@ class Allocator
807818
if (!slBitmasks[fl]) flBitmask = Mask(flBitmask,FlipBits(BitMask(fl)));
808819
}
809820

810-
// void RemoveFromFreeList(BlockHeader* block)
811-
// {
812-
// size_t size = GetHeaderSize(block);
813-
// size_t fl, sl, index;
814-
//
815-
// FreeBlockNode* freeBlock = FindFreeBlock(size, fl, sl, index);
816-
// RemoveFromFreeList(freeBlock, fl, sl, index);
817-
// }
821+
void RemoveFromFreeList(BlockHeader* block)
822+
{
823+
size_t size = GetHeaderSize(block);
824+
size_t fl, sl, index;
825+
826+
CalculateIndices(size, fl, sl, index);
827+
828+
FreeBlockNode* freeBlock = TO_FREEBLOCK((TO_BYTES(block) + sizeof(BlockHeader)));
829+
RemoveFromFreeList(freeBlock, fl, sl, index);
830+
}
818831

819832
void CalculateIndices(size_t size, OUT size_t& fl, OUT size_t& sl, OUT size_t& index)
820833
{
@@ -830,11 +843,11 @@ class Allocator
830843
size_t sizeFlag = (size << FLAG_BITS);
831844

832845
BlockHeader* header = TO_HBLOCK(ptr);
833-
header->sizeAndFlags = sizeFlag;
846+
header->sizeAndFlags = (sizeFlag | IS_FREE_FLAG);
834847

835848
FreeBlockNode* block = TO_FREEBLOCK((TO_BYTES(header) + sizeof(BlockHeader)));
836849

837-
BlockFooter* firstFooter = TO_FBLOCK((TO_BYTES(block)+size));
850+
BlockFooter* firstFooter = TO_FBLOCK((TO_BYTES(header)+(size-sizeof(BlockFooter))));
838851
firstFooter->totalBlockSize = size;
839852

840853
block->next = freeList[index];
@@ -982,36 +995,99 @@ UTEST(test_ResourceSystem, TestAllocateFunction)
982995
void* overflowPtr = overflowAlloc.Allocate(SIZE_T_MAX);
983996
ASSERT_FALSE(overflowPtr);
984997
}
985-
//
986-
//UTEST(test_ResourceSystem, TestDeallocateFunction)
987-
//{
988-
// Allocator a(64);
989-
// ASSERT_NE(a.Data(), nullptr);
990-
// ASSERT_EQ(a.Capacity(), 64);
991-
//
992-
// TestStruct* p = (TestStruct*) a.Allocate(sizeof(TestStruct));
993-
//
994-
// p->inta = 10;
995-
// p->intb = 20;
996-
//
997-
// ASSERT_EQ(10, p->inta);
998-
// ASSERT_EQ(20, p->intb);
999-
//
1000-
// ASSERT_EQ(a.FlBitmask(), 2);
1001-
// ASSERT_EQ(16, a.SlBitmask()[1]);
1002-
//
1003-
// FreeBlock* block = a.FreeList()[(1 * 16) + 4];
1004-
// ASSERT_EQ(block->size,40);
1005-
// ASSERT_EQ(block->next, nullptr);
1006-
// ASSERT_EQ(block->prev, nullptr);
1007-
//
1008-
// auto header = (BlockHeader*)a.Data();
1009-
// auto data = (TestStruct*) (((unsigned char*)header) + sizeof(BlockHeader));
1010-
// auto footer = (BlockFooter*) (((unsigned char*)data) + sizeof(TestStruct));
1011-
//
1012-
// ASSERT_EQ(192, header->sizeAndFlags);
1013-
// ASSERT_EQ(data, p);
1014-
// ASSERT_EQ(sizeof(BlockHeader) + sizeof(TestStruct) + sizeof(BlockFooter), footer->totalBlockSize);
1015-
//
1016-
// a.Deallocate(p);
1017-
//}
998+
999+
UTEST(test_ResourceSystem, TestDeallocateFunction)
1000+
{
1001+
Allocator a(64);
1002+
ASSERT_NE(a.Data(), nullptr);
1003+
ASSERT_EQ(a.Capacity(), 64);
1004+
1005+
TestStruct* p = (TestStruct*) a.Allocate(sizeof(TestStruct));
1006+
1007+
p->inta = 10;
1008+
p->intb = 20;
1009+
1010+
ASSERT_EQ(10, p->inta);
1011+
ASSERT_EQ(20, p->intb);
1012+
1013+
ASSERT_EQ(a.FlBitmask(), 2);
1014+
ASSERT_EQ(16, a.SlBitmask()[1]);
1015+
1016+
FreeBlockNode* block = a.FreeList()[(1 * 16) + 4];
1017+
ASSERT_EQ(block->next, nullptr);
1018+
ASSERT_EQ(block->prev, nullptr);
1019+
1020+
auto header = (BlockHeader*)a.Data();
1021+
auto data = (TestStruct*) (((unsigned char*)header) + sizeof(BlockHeader));
1022+
auto footer = (BlockFooter*) (((unsigned char*)data) + sizeof(TestStruct));
1023+
1024+
ASSERT_EQ(192, header->sizeAndFlags);
1025+
ASSERT_EQ(data, p);
1026+
ASSERT_EQ(sizeof(BlockHeader) + sizeof(TestStruct) + sizeof(BlockFooter), footer->totalBlockSize);
1027+
1028+
a.Deallocate(p);
1029+
1030+
// Should be empty
1031+
ASSERT_EQ(513, header->sizeAndFlags);
1032+
ASSERT_TRUE(header->sizeAndFlags & IS_FREE_FLAG);
1033+
ASSERT_FALSE(p);
1034+
ASSERT_EQ(a.FlBitmask(), 4);
1035+
ASSERT_EQ(a.SlBitmask()[2], 1);
1036+
1037+
p = (TestStruct*) a.Allocate(sizeof(TestStruct));
1038+
p->inta = 10;
1039+
p->intb = 20;
1040+
1041+
ASSERT_EQ(10, p->inta);
1042+
ASSERT_EQ(20, p->intb);
1043+
1044+
ASSERT_EQ(a.FlBitmask(), 2);
1045+
ASSERT_EQ(16, a.SlBitmask()[1]);
1046+
1047+
block = a.FreeList()[(1 * 16) + 4];
1048+
ASSERT_EQ(block->next, nullptr);
1049+
ASSERT_EQ(block->prev, nullptr);
1050+
1051+
header = (BlockHeader*)a.Data();
1052+
data = (TestStruct*) (((unsigned char*)header) + sizeof(BlockHeader));
1053+
footer = (BlockFooter*) (((unsigned char*)data) + sizeof(TestStruct));
1054+
1055+
ASSERT_EQ(192, header->sizeAndFlags);
1056+
ASSERT_EQ(data, p);
1057+
ASSERT_EQ(sizeof(BlockHeader) + sizeof(TestStruct) + sizeof(BlockFooter), footer->totalBlockSize);
1058+
1059+
Siege::String* str = (Siege::String*) a.Allocate(sizeof(Siege::String));
1060+
1061+
*str = "Hello There!";
1062+
ASSERT_STREQ(str->Str(),"Hello There!");
1063+
1064+
ASSERT_EQ(1, a.FlBitmask());
1065+
ASSERT_EQ(0, a.SlBitmask()[1]);
1066+
1067+
FreeBlockNode* NewBlock = a.FreeList()[0];
1068+
ASSERT_EQ(NewBlock->next, nullptr);
1069+
ASSERT_EQ(NewBlock->prev, nullptr);
1070+
1071+
auto newHeader = (BlockHeader*)(TO_BYTES(footer) + sizeof(BlockFooter));
1072+
auto newData = (Siege::String*) (((unsigned char*)newHeader) + sizeof(BlockHeader));
1073+
auto newFooter = (BlockFooter*) (((unsigned char*)newData) + sizeof(TestStruct));
1074+
1075+
ASSERT_EQ(194, newHeader->sizeAndFlags);
1076+
ASSERT_EQ(newData, str);
1077+
ASSERT_EQ(sizeof(BlockHeader) + sizeof(Siege::String) + sizeof(BlockFooter), newFooter->totalBlockSize);
1078+
1079+
a.Deallocate(p);
1080+
ASSERT_FALSE(p);
1081+
ASSERT_TRUE(newHeader->sizeAndFlags & IS_PREV_FREE_FLAG);
1082+
ASSERT_EQ(194, newHeader->sizeAndFlags);
1083+
ASSERT_TRUE(header->sizeAndFlags & IS_FREE_FLAG);
1084+
FreeBlockNode* newFreeBlock = TO_FREEBLOCK((TO_BYTES(header)+sizeof(BlockHeader)));
1085+
ASSERT_EQ(newFreeBlock->next, nullptr);
1086+
ASSERT_EQ(newFreeBlock->prev, nullptr);
1087+
1088+
a.Deallocate(str);
1089+
// ASSERT_FALSE(str);
1090+
// ASSERT_EQ(513, header->sizeAndFlags);
1091+
// ASSERT_EQ(a.FlBitmask(), 4);
1092+
// ASSERT_EQ(a.SlBitmask()[2], 1);
1093+
}

0 commit comments

Comments
 (0)