15#ifndef FASTLED_DEFAULT_SLAB_SIZE
16#define FASTLED_DEFAULT_SLAB_SIZE 8
22template <
typename Po
inter,
typename SizeType>
30template <
typename Allocator>
34 using pointer =
typename Allocator::pointer;
39 template <
typename A = Allocator,
typename =
void>
44 fl::declval<typename A::pointer>(),
45 fl::declval<typename A::size_type>(),
46 fl::declval<typename A::size_type>()
53 template <
typename A = Allocator,
typename =
void>
58 fl::declval<typename A::size_type>()
65#if defined(FASTLED_TESTING)
70 virtual void onMalloc(
void* ptr, fl::size size)
FL_NOEXCEPT = 0;
75void SetMallocFreeHook(MallocFreeHook* hook)
FL_NOEXCEPT;
110void* InternalAlloc(fl::size size);
111void* InternalRealloc(
void* ptr, fl::size size);
112void InternalFree(
void* ptr);
113void* DMAAlloc(fl::size size);
114void DMAFree(
void* ptr);
145 template <
typename U>
154 template <
typename U>
183 if (new_count == 0) {
196 T* new_ptr =
static_cast<T*
>(
result);
199 if (new_count > old_count) {
200 fl::memset(new_ptr + old_count, 0, (new_count - old_count) *
sizeof(T));
223 fl::size size =
sizeof(T) * n;
225 if (ptr ==
nullptr) {
229 return static_cast<T*
>(ptr);
241 template <
typename U,
typename... Args>
243 if (p ==
nullptr)
return;
248 template <
typename U>
250 if (p ==
nullptr)
return;
275 "allocator_realloc<T> requires T to be trivially copyable. "
276 "NOTE: This allocator is now redundant - fl::allocator<T> automatically "
277 "optimizes trivially copyable types. Just use fl::vector<T> instead.");
290 template <
typename U>
299 template <
typename U>
310 fl::size size =
sizeof(T) * n;
312 if (ptr ==
nullptr) {
316 return static_cast<T*
>(ptr);
329 template <
typename U,
typename... Args>
331 if (p ==
nullptr)
return;
336 template <
typename U>
338 if (p ==
nullptr)
return;
349 fl::size requested = (3 * n) / 2;
352 return {ptr, requested};
356 return {ptr, ptr ? n : 0};
363 if (new_count == 0) {
376 T* new_ptr =
static_cast<T*
>(
result);
379 if (new_count > old_count) {
380 fl::memset(new_ptr + old_count, 0, (new_count - old_count) *
sizeof(T));
399 template <
typename U>
408 template <
typename U>
426 template <
typename U,
typename... Args>
428 if (p ==
nullptr)
return;
433 template <
typename U>
435 if (p ==
nullptr)
return;
460template <
typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE>
464 static constexpr fl::size
SLAB_BLOCK_SIZE =
sizeof(T) >
sizeof(
void*) ?
sizeof(T) : sizeof(void*);
515 for (
Slab* slab =
mSlabs; slab; slab = slab->next) {
543 fl::i32 start = slab->allocated_blocks.find_run(
false,
static_cast<fl::u32
>(n));
546 for (fl::size i = 0; i < n; ++i) {
547 slab->allocated_blocks.set(
static_cast<fl::u32
>(start + i),
true);
549 slab->allocated_count += n;
565 for (
Slab* slab =
mSlabs; slab; slab = slab->next) {
566 u8* slab_start = slab->memory;
570 if (block_ptr >= slab_start && block_ptr < slab_end) {
574 for (fl::size i = 0; i < n; ++i) {
576 slab->allocated_blocks.set(block_index + i,
false);
580 slab->allocated_count -= n;
603 other.mSlabs =
nullptr;
604 other.mTotalAllocated = 0;
605 other.mTotalDeallocated = 0;
609 if (
this != &other) {
614 other.mSlabs =
nullptr;
615 other.mTotalAllocated = 0;
616 other.mTotalDeallocated = 0;
630 return static_cast<T*
>(ptr);
634 ptr =
Malloc(
sizeof(T) * n);
638 return static_cast<T*
>(ptr);
647 bool found_in_slab =
false;
648 for (
Slab* slab =
mSlabs; slab; slab = slab->next) {
649 u8* slab_start = slab->memory;
653 if (block_ptr >= slab_start && block_ptr < slab_end) {
655 found_in_slab =
true;
660 if (!found_in_slab) {
674 for (
Slab* slab =
mSlabs; slab; slab = slab->next) {
694template <
typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE>
707 template <
typename U>
731 template <
typename U>
744 constexpr fl::size block_size =
sizeof(T) >
sizeof(
void*) ?
sizeof(T) :
sizeof(
void*);
771 template <
typename U,
typename... Args>
773 if (p ==
nullptr)
return;
778 template <
typename U>
780 if (p ==
nullptr)
return;
798 return !(*
this == other);
804template <
typename T, fl::size N,
typename BaseAllocator = fl::allocator<T>>
834 template <
typename U>
861 if (
this != &other) {
882 template <
typename U>
909 fl::i32 free_slot =
mFreeBits.find_first(
false);
910 if (free_slot >= 0 &&
static_cast<fl::size
>(free_slot) < N) {
912 mFreeBits.set(
static_cast<fl::u32
>(free_slot),
true);
915 if (
static_cast<fl::size
>(free_slot) + 1 >
mInlinedUsed) {
938 T* inlined_end = inlined_start + N;
940 if (p >= inlined_start && p < inlined_end) {
942 fl::size slot_index = (p - inlined_start);
943 for (fl::size i = 0; i < n; ++i) {
944 if (slot_index + i < N) {
958 template <
typename U,
typename... Args>
960 if (p ==
nullptr)
return;
965 template <
typename U>
967 if (p ==
nullptr)
return;
1010 template<
typename U>
1013 template<
typename U>
1038 return !(*
this == other);
1043template <
typename T, fl::size N>
1047template <
typename T, fl::size N, fl::size SLAB_SIZE = 8>
1050template <
typename T, fl::size N>
Alignment macros and utilities for FastLED.
static void Free(T *p) FL_NOEXCEPT
static T * Alloc(fl::size n) FL_NOEXCEPT
SlabAllocator(SlabAllocator &&other) FL_NOEXCEPT
SlabAllocator(const SlabAllocator &) FL_NOEXCEPT=delete
Slab * createSlab() FL_NOEXCEPT
static constexpr fl::size BLOCKS_PER_SLAB
void * allocateFromSlab(fl::size n=1) FL_NOEXCEPT
fl::size getSlabCount() const FL_NOEXCEPT
T * allocate(fl::size n=1) FL_NOEXCEPT
fl::size mTotalDeallocated
fl::size getTotalAllocated() const FL_NOEXCEPT
~SlabAllocator() FL_NOEXCEPT
static constexpr fl::size SLAB_MEMORY_SIZE
void cleanup() FL_NOEXCEPT
fl::size getActiveAllocations() const FL_NOEXCEPT
static constexpr fl::size SLAB_BLOCK_SIZE
void deallocate(T *ptr, fl::size n=1) FL_NOEXCEPT
void deallocateToSlab(void *ptr, fl::size n=1) FL_NOEXCEPT
SlabAllocator() FL_NOEXCEPT
void * findContiguousBlocks(Slab *slab, fl::size n) FL_NOEXCEPT
fl::size getTotalDeallocated() const FL_NOEXCEPT
SlabAllocator & operator=(const SlabAllocator &) FL_NOEXCEPT=delete
SlabAllocator & operator=(SlabAllocator &&other) FL_NOEXCEPT
BaseAllocator mBaseAllocator
bool operator==(const allocator_inlined &other) const FL_NOEXCEPT
InlinedStorage mInlinedStorage
fl::size mActiveAllocations
bool is_using_inlined() const FL_NOEXCEPT
void destroy(U *p) FL_NOEXCEPT
void deallocate(T *p, fl::size n) FL_NOEXCEPT
const T * get_inlined_ptr() const FL_NOEXCEPT
~allocator_inlined() FL_NOEXCEPT
allocator_inlined() FL_NOEXCEPT=default
void construct(U *p, Args &&... args) FL_NOEXCEPT
fl::size inlined_capacity() const FL_NOEXCEPT
decltype(has_cleanup_impl< BaseAllocator >(0)) has_cleanup
const T & const_reference
static fl::false_type has_cleanup_impl(...) FL_NOEXCEPT
void cleanup_base_allocator() FL_NOEXCEPT
T * allocate(fl::size n) FL_NOEXCEPT
static auto has_cleanup_impl(int) FL_NOEXCEPT -> decltype(fl::declval< U >().cleanup(), fl::true_type{})
void cleanup_base_allocator_impl(fl::true_type) FL_NOEXCEPT
allocator_inlined & operator=(const allocator_inlined &other) FL_NOEXCEPT
fl::ptrdiff_t difference_type
allocator_inlined(const allocator_inlined< U, N, typename BaseAllocator::template rebind< U >::other > &other) FL_NOEXCEPT
T * get_inlined_ptr() FL_NOEXCEPT
void cleanup_base_allocator_impl(fl::false_type) FL_NOEXCEPT
bool operator!=(const allocator_inlined &other) const FL_NOEXCEPT
fl::bitset_fixed< N > mFreeBits
fl::size total_size() const FL_NOEXCEPT
allocator_inlined< U, N, typename BaseAllocator::template rebind< U >::other > other
~allocator_psram() FL_NOEXCEPT
allocator_psram(const allocator_psram< U > &) FL_NOEXCEPT
void destroy(U *p) FL_NOEXCEPT
void construct(U *p, Args &&... args) FL_NOEXCEPT
allocator_psram() FL_NOEXCEPT
const T & const_reference
T * allocate(fl::size n) FL_NOEXCEPT
pointer reallocate(pointer ptr, fl::size old_count, fl::size new_count) FL_NOEXCEPT
void deallocate(T *p, fl::size n) FL_NOEXCEPT
allocation_result< pointer, size_type > allocate_at_least(fl::size n) FL_NOEXCEPT
fl::ptrdiff_t difference_type
allocator_psram< U > other
pointer reallocate(pointer ptr, fl::size old_count, fl::size new_count) FL_NOEXCEPT
const T & const_reference
allocation_result< pointer, size_type > allocate_at_least(fl::size n) FL_NOEXCEPT
void destroy(U *p) FL_NOEXCEPT
allocator_realloc(const allocator_realloc< U > &) FL_NOEXCEPT
FL_STATIC_ASSERT(fl::is_trivially_copyable< T >::value, "allocator_realloc<T> requires T to be trivially copyable. " "NOTE: This allocator is now redundant - fl::allocator<T> automatically " "optimizes trivially copyable types. Just use fl::vector<T> instead.")
allocator_realloc() FL_NOEXCEPT
void deallocate(T *p, fl::size n) FL_NOEXCEPT
T * allocate(fl::size n) FL_NOEXCEPT
void construct(U *p, Args &&... args) FL_NOEXCEPT
fl::ptrdiff_t difference_type
~allocator_realloc() FL_NOEXCEPT
allocator_realloc< U > other
void destroy(U *p) FL_NOEXCEPT
allocator_slab() FL_NOEXCEPT
bool operator==(const allocator_slab &other) const FL_NOEXCEPT
void deallocate(T *p, fl::size n) FL_NOEXCEPT
allocator_slab & operator=(const allocator_slab &other) FL_NOEXCEPT
T * allocate(fl::size n) FL_NOEXCEPT
bool operator!=(const allocator_slab &other) const FL_NOEXCEPT
fl::ptrdiff_t difference_type
const T & const_reference
allocator_slab(const allocator_slab &other) FL_NOEXCEPT
static SlabAllocator< T, SLAB_SIZE > & get_allocator() FL_NOEXCEPT
void construct(U *p, Args &&... args) FL_NOEXCEPT
~allocator_slab() FL_NOEXCEPT
allocator_slab(const allocator_slab< U, SLAB_SIZE > &other) FL_NOEXCEPT
void cleanup() FL_NOEXCEPT
typename fl::conditional< fl::is_same< U, void >::value, allocator_slab< char, SLAB_SIZE >, allocator_slab< U, SLAB_SIZE > >::type other
pointer reallocate_impl(pointer ptr, fl::size old_count, fl::size new_count, fl::false_type) FL_NOEXCEPT
allocation_result< pointer, size_type > allocate_at_least(fl::size n) FL_NOEXCEPT
void deallocate(T *p, fl::size n) FL_NOEXCEPT
T * allocate(fl::size n) FL_NOEXCEPT
fl::ptrdiff_t difference_type
void construct(U *p, Args &&... args) FL_NOEXCEPT
void destroy(U *p) FL_NOEXCEPT
const T & const_reference
pointer reallocate_impl(pointer ptr, fl::size old_count, fl::size new_count, fl::true_type) FL_NOEXCEPT
pointer reallocate(pointer ptr, fl::size old_count, fl::size new_count) FL_NOEXCEPT
allocator(const allocator< U > &) FL_NOEXCEPT
void * slab_allocator_registry_get(fl::size block_size, fl::size slab_size)
void slab_allocator_registry_set(fl::size block_size, fl::size slab_size, void *allocator)
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
integral_constant< bool, true > true_type
add_rvalue_reference< T >::type declval() FL_NOEXCEPT
integral_constant< bool, false > false_type
add_rvalue_reference< T >::type declval() FL_NOEXCEPT
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
void SetPSRamAllocator(void *(*alloc)(fl::size), void(*free)(void *))
expected< T, E > result
Alias for expected (Rust-style naming)
void PSRamDeallocate(void *ptr)
void * Malloc(fl::size size)
void * realloc(void *ptr, size_t new_size)
allocator_inlined< T, N, fl::allocator_slab< T > > allocator_inlined_slab
To * bit_cast_ptr(void *storage) FL_NOEXCEPT
void * PSRamAllocate(fl::size size, bool zero)
allocator_inlined< T, N, fl::allocator_slab< T, SLAB_SIZE > > allocator_inlined_slab_psram
allocator_inlined< T, N, fl::allocator_psram< T > > allocator_inlined_psram
Base definition for an LED controller.
#define FASTLED_UNUSED(x)
Portable compile-time assertion wrapper.
PSRamDeleter() FL_NOEXCEPT=default
fl::bitset_fixed< BLOCKS_PER_SLAB > allocated_blocks
InlinedStorage() FL_NOEXCEPT
FL_ALIGN_AS(T) u8 data[N *sizeof(T)]
typename Allocator::pointer pointer
static constexpr bool has_allocate_at_least_v
typename Allocator::value_type value_type
static constexpr bool has_reallocate_v
typename Allocator::size_type size_type