| 459 | // Uses pre-allocated memory slabs with free lists to reduce fragmentation |
| 460 | template <typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE> |
| 461 | class SlabAllocator { |
| 462 | private: |
| 463 | |
| 464 | static constexpr fl::size SLAB_BLOCK_SIZE = sizeof(T) > sizeof(void*) ? sizeof(T) : sizeof(void*); |
| 465 | static constexpr fl::size BLOCKS_PER_SLAB = SLAB_SIZE; |
| 466 | static constexpr fl::size SLAB_MEMORY_SIZE = SLAB_BLOCK_SIZE * BLOCKS_PER_SLAB; |
| 467 | |
| 468 | struct Slab { |
| 469 | Slab* next; |
| 470 | u8* memory; |
| 471 | fl::size allocated_count; |
| 472 | fl::bitset_fixed<BLOCKS_PER_SLAB> allocated_blocks; // Track which blocks are allocated |
| 473 | |
| 474 | Slab() FL_NOEXCEPT : next(nullptr), memory(nullptr), allocated_count(0) {} |
| 475 | |
| 476 | ~Slab() FL_NOEXCEPT { |
| 477 | if (memory) { |
| 478 | Free(memory); |
| 479 | } |
| 480 | } |
| 481 | }; |
| 482 | |
| 483 | Slab* mSlabs; |
| 484 | fl::size mTotalAllocated; |
| 485 | fl::size mTotalDeallocated; |
| 486 | |
| 487 | Slab* createSlab() FL_NOEXCEPT { |
| 488 | Slab* slab = static_cast<Slab*>(Malloc(sizeof(Slab))); |
| 489 | if (!slab) { |
| 490 | return nullptr; |
| 491 | } |
| 492 | |
| 493 | // Use placement new to properly initialize the Slab |
| 494 | new(slab) Slab(); |
| 495 | |
| 496 | slab->memory = static_cast<u8*>(Malloc(SLAB_MEMORY_SIZE)); |
| 497 | if (!slab->memory) { |
| 498 | slab->~Slab(); |
| 499 | Free(slab); |
| 500 | return nullptr; |
| 501 | } |
| 502 | |
| 503 | // Initialize all blocks in the slab as free |
| 504 | slab->allocated_blocks.reset(); // All blocks start as free |
| 505 | |
| 506 | // Add slab to the slab list |
| 507 | slab->next = mSlabs; |
| 508 | mSlabs = slab; |
| 509 | |
| 510 | return slab; |
| 511 | } |
| 512 | |
| 513 | void* allocateFromSlab(fl::size n = 1) FL_NOEXCEPT { |
| 514 | // Try to find n contiguous free blocks in existing slabs |
| 515 | for (Slab* slab = mSlabs; slab; slab = slab->next) { |
| 516 | void* ptr = findContiguousBlocks(slab, n); |
| 517 | if (ptr) { |
| 518 | return ptr; |