16
16
#include < resources/StaticMeshData.h>
17
17
#include < resources/Texture2DData.h>
18
18
#include < utest.h>
19
+ #include < random>
19
20
20
21
using namespace Siege ;
21
22
@@ -683,7 +684,9 @@ class Allocator
683
684
684
685
if (freeListIdx == INVALID_INDEX) return nullptr ;
685
686
686
- BlockHeader* header = GetHeader (block);
687
+ BlockHeader* header = reinterpret_cast <BlockHeader*>(reinterpret_cast <unsigned char *>(block) - sizeof (BlockHeader));
688
+
689
+
687
690
688
691
TrySplitBlock (header, block, requiredSize, fl, sl, freeListIdx);
689
692
@@ -694,7 +697,7 @@ class Allocator
694
697
695
698
newHeader->sizeAndFlags = (requiredSize << FLAG_BITS) | flags;
696
699
697
- unsigned char * ptr = TO_BYTES (TO_BYTES ( header)+sizeof (BlockHeader) );
700
+ unsigned char * ptr = TO_BYTES (header)+sizeof (BlockHeader);
698
701
699
702
BlockFooter* footer = TO_FBLOCK ((ptr+size));
700
703
footer->totalBlockSize = requiredSize;
@@ -732,8 +735,10 @@ class Allocator
732
735
733
736
size_t GetNextFreeSlotIndex (OUT size_t & fl,OUT size_t & sl)
734
737
{
735
- sl = FindLargerSlots (slBitmasks[fl], sl);
736
- if (sl) return fl * MAX_SL_INDEX + __builtin_ctz (sl);
738
+ sl = __builtin_ctz (FindLargerSlots (slBitmasks[fl], sl));
739
+
740
+ if (sl == 32 ) sl = 0 ;
741
+ if (sl) return fl * MAX_SL_INDEX + sl;
737
742
738
743
fl = FindLargerSlots64 (flBitmask, fl);
739
744
@@ -813,18 +818,19 @@ class Allocator
813
818
{
814
819
size_t blockSize = GetHeaderSize (header);
815
820
RemoveFromFreeList (block, fl, sl, index);
816
- if (blockSize <= size) return ;
821
+ if (blockSize <= size || ((blockSize - size) < ( sizeof (BlockHeader) + sizeof (BlockFooter))) ) return ;
817
822
818
823
CreateNewBlock (TO_BYTES (header) + size, blockSize - size);
819
824
}
820
825
821
826
void RemoveFromFreeList (FreeBlockNode* block, size_t fl, size_t sl, size_t index)
822
827
{
823
828
if (!block) return ;
824
- if (block->prev ) block->prev ->next = block->next ;
825
- if (block->next ) block->next ->prev = block->prev ;
826
829
827
- freeList[index] = block->next ;
830
+ if (!block->prev ) freeList[index] = block->next ;
831
+ else block->prev ->next = block->next ;
832
+
833
+ if (block->next ) block->next ->prev = block->prev ;
828
834
829
835
slBitmasks[fl] = Mask (slBitmasks[fl],FlipBits (BitMask (sl)));
830
836
if (!slBitmasks[fl]) flBitmask = Mask (flBitmask,FlipBits (BitMask (fl)));
@@ -857,15 +863,17 @@ class Allocator
857
863
BlockHeader* header = TO_HBLOCK (ptr);
858
864
header->sizeAndFlags = (sizeFlag | IS_FREE_FLAG);
859
865
860
- FreeBlockNode* block = TO_FREEBLOCK ((TO_BYTES (header) + sizeof (BlockHeader)));
866
+ FreeBlockNode* block = reinterpret_cast <FreeBlockNode*>(reinterpret_cast <unsigned char *>(header) + sizeof (BlockHeader));
867
+
868
+ // FreeBlockNode* block = TO_FREEBLOCK((TO_BYTES(header) + sizeof(BlockHeader)));
861
869
862
870
BlockFooter* firstFooter = TO_FBLOCK ((TO_BYTES (header)+(size-sizeof (BlockFooter))));
863
871
firstFooter->totalBlockSize = size;
864
872
865
873
block->next = freeList[index];
866
874
block->prev = nullptr ;
867
875
868
- if (block->next ) block->next ->prev = block;
876
+ if (IsValid ( block->next ) ) block->next ->prev = block;
869
877
870
878
freeList[index] = block;
871
879
@@ -892,6 +900,7 @@ class Allocator
892
900
893
901
bool IsHead (void * ptr) { return TO_BYTES (ptr) == data ;}
894
902
bool IsTail (void * ptr) { return TO_BYTES (ptr) + sizeof (BlockHeader) >= (data + capacity); }
903
+ bool IsValid (FreeBlockNode* ptr) { return ptr != nullptr ; }
895
904
size_t & Capacity () { return capacity;}
896
905
unsigned char * Data () { return data; };
897
906
size_t SlIndex (size_t size, size_t fl) { return (size >> (fl - SL_BITS)) & SL_MASK; }
@@ -1260,3 +1269,52 @@ UTEST(test_ResourceSystem, TestAllocationWhenNoAppropriateFragmentExists)
1260
1269
void * tooLargeVal = a.Allocate (24 );
1261
1270
ASSERT_FALSE (tooLargeVal);
1262
1271
}
1272
+
1273
+ UTEST (test_ResourceSystem, TestRandomAllocationsAndDeallocations)
1274
+ {
1275
+ Allocator a (1024 * 1024 );
1276
+
1277
+ unsigned seed = std::chrono::steady_clock::now ().time_since_epoch ().count ();
1278
+ // std::default_random_engine generator(seed);
1279
+ std::default_random_engine generator (12345 );
1280
+
1281
+ std::uniform_int_distribution<int > actionDist (0 , 10 );
1282
+ std::uniform_int_distribution<int > sizeDist (1 , 256 );
1283
+
1284
+ std::vector<void *> pointers;
1285
+
1286
+ for (int i = 0 ; i < 10000 ; i++)
1287
+ {
1288
+ int action = actionDist (generator);
1289
+
1290
+ if (action < 8 )
1291
+ {
1292
+ size_t randomSize = sizeDist (generator);
1293
+ void * ptr = a.Allocate (randomSize);
1294
+ if (ptr)
1295
+ {
1296
+ *((uint32_t *)ptr) = 0xDEADC0DE ;
1297
+ pointers.push_back (ptr);
1298
+ }
1299
+ }
1300
+ else if (action <= 10 && !pointers.empty ())
1301
+ {
1302
+ std::uniform_int_distribution<int > indices (0 , pointers.size ()-1 );
1303
+ size_t index = indices (generator);
1304
+
1305
+ void * ptrToFree = pointers[index];
1306
+ ASSERT_EQ (*(uint32_t *)ptrToFree, 0xDEADC0DE );
1307
+
1308
+ a.Deallocate (ptrToFree);
1309
+ ASSERT_FALSE (ptrToFree);
1310
+ pointers.erase (pointers.begin () + index);
1311
+ }
1312
+ }
1313
+
1314
+ for (void * ptr : pointers)
1315
+ {
1316
+ a.Deallocate (ptr);
1317
+ }
1318
+
1319
+ ASSERT_EQ (a.Capacity (), a.BytesRemaining ());
1320
+ }
0 commit comments