@@ -697,16 +697,28 @@ class Allocator
697
697
return ptr;
698
698
}
699
699
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
+
710
722
size_t GetNextFreeSlotIndex (OUT size_t & fl,OUT size_t & sl)
711
723
{
712
724
sl = FindLargerSlots (slBitmasks[fl], sl);
@@ -734,35 +746,34 @@ class Allocator
734
746
const size_t SetBitOn (size_t val, size_t bit) { return val | BitMask (bit);}
735
747
const size_t FlipBits (size_t mask) { return ~(mask); }
736
748
const size_t Mask (size_t value, size_t mask) { return value & mask; }
737
- //
749
+
738
750
const size_t GetHeaderSize (BlockHeader* header) { return header->sizeAndFlags >> FLAG_BITS; }
739
751
const size_t PrevBlockIsFree (BlockHeader* header) { return Mask (header->sizeAndFlags , IS_PREV_FREE_FLAG); }
740
752
const size_t BlockIsFree (BlockHeader* header) { return Mask (header->sizeAndFlags , IS_FREE_FLAG); }
741
753
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
+ }
766
777
767
778
BlockHeader* GetPreviousHeader (void * currentHeader)
768
779
{
@@ -772,19 +783,19 @@ class Allocator
772
783
return prevHeader;
773
784
}
774
785
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
+ }
782
793
783
794
void TrySetPreviousHeaderFlag (void * currentHeader, size_t & flags)
784
795
{
785
796
BlockHeader* prevHeader = GetPreviousHeader (currentHeader);
786
797
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;
788
799
}
789
800
790
801
void TrySplitBlock (BlockHeader* header, FreeBlockNode* block, size_t size, size_t fl, size_t sl, size_t index)
@@ -807,14 +818,16 @@ class Allocator
807
818
if (!slBitmasks[fl]) flBitmask = Mask (flBitmask,FlipBits (BitMask (fl)));
808
819
}
809
820
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
+ }
818
831
819
832
void CalculateIndices (size_t size, OUT size_t & fl, OUT size_t & sl, OUT size_t & index)
820
833
{
@@ -830,11 +843,11 @@ class Allocator
830
843
size_t sizeFlag = (size << FLAG_BITS);
831
844
832
845
BlockHeader* header = TO_HBLOCK (ptr);
833
- header->sizeAndFlags = sizeFlag;
846
+ header->sizeAndFlags = ( sizeFlag | IS_FREE_FLAG) ;
834
847
835
848
FreeBlockNode* block = TO_FREEBLOCK ((TO_BYTES (header) + sizeof (BlockHeader)));
836
849
837
- BlockFooter* firstFooter = TO_FBLOCK ((TO_BYTES (block)+ size));
850
+ BlockFooter* firstFooter = TO_FBLOCK ((TO_BYTES (header)+( size- sizeof (BlockFooter)) ));
838
851
firstFooter->totalBlockSize = size;
839
852
840
853
block->next = freeList[index];
@@ -982,36 +995,99 @@ UTEST(test_ResourceSystem, TestAllocateFunction)
982
995
void * overflowPtr = overflowAlloc.Allocate (SIZE_T_MAX);
983
996
ASSERT_FALSE (overflowPtr);
984
997
}
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