| 693 | // STL-compatible slab allocator |
| 694 | template <typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE> |
| 695 | class allocator_slab { |
| 696 | public: |
| 697 | // Type definitions required by STL |
| 698 | using value_type = T; |
| 699 | using pointer = T*; |
| 700 | using const_pointer = const T*; |
| 701 | using reference = T&; |
| 702 | using const_reference = const T&; |
| 703 | using size_type = fl::size; |
| 704 | using difference_type = fl::ptrdiff_t; |
| 705 | |
| 706 | // Rebind allocator to type U |
| 707 | template <typename U> |
| 708 | struct rebind { |
| 709 | using other = typename fl::conditional< |
| 710 | fl::is_same<U, void>::value, |
| 711 | allocator_slab<char, SLAB_SIZE>, |
| 712 | allocator_slab<U, SLAB_SIZE> |
| 713 | >::type; |
| 714 | }; |
| 715 | |
| 716 | // Default constructor |
| 717 | allocator_slab() FL_NOEXCEPT {} |
| 718 | |
| 719 | // Copy constructor |
| 720 | allocator_slab(const allocator_slab& other) FL_NOEXCEPT { |
| 721 | FASTLED_UNUSED(other); |
| 722 | } |
| 723 | |
| 724 | // Copy assignment |
| 725 | allocator_slab& operator=(const allocator_slab& other) FL_NOEXCEPT { |
| 726 | FASTLED_UNUSED(other); |
| 727 | return *this; |
| 728 | } |
| 729 | |
| 730 | // Template copy constructor |
| 731 | template <typename U> |
| 732 | allocator_slab(const allocator_slab<U, SLAB_SIZE>& other) FL_NOEXCEPT { |
| 733 | FASTLED_UNUSED(other); |
| 734 | } |
| 735 | |
| 736 | // Destructor |
| 737 | ~allocator_slab() FL_NOEXCEPT {} |
| 738 | |
| 739 | private: |
| 740 | // Get the shared process-wide allocator instance. |
| 741 | // Uses a DLL-exported registry to ensure all DLLs in the process share |
| 742 | // the same SlabAllocator for a given (block_size, slab_size) pair. |
| 743 | static SlabAllocator<T, SLAB_SIZE>& get_allocator() FL_NOEXCEPT { |
| 744 | constexpr fl::size block_size = sizeof(T) > sizeof(void*) ? sizeof(T) : sizeof(void*); |
| 745 | void* ptr = detail::slab_allocator_registry_get(block_size, SLAB_SIZE); |
| 746 | if (ptr) { |
| 747 | return *static_cast<SlabAllocator<T, SLAB_SIZE>*>(ptr); |
| 748 | } |
| 749 | // First time for this (block_size, slab_size) pair - create and register |
| 750 | static SlabAllocator<T, SLAB_SIZE> allocator; |
| 751 | detail::slab_allocator_registry_set(block_size, SLAB_SIZE, &allocator); |
| 752 | return allocator; |
nothing calls this directly
no test coverage detected