FastLED 3.9.15
Loading...
Searching...
No Matches
allocator.h
Go to the documentation of this file.
1#pragma once
2
3#include <stdlib.h>
4#include <string.h>
5#include "fl/inplacenew.h"
6#include "fl/memfill.h"
7#include "fl/type_traits.h"
8#include "fl/unused.h"
9#include "fl/bit_cast.h"
10#include "fl/stdint.h"
11#include "fl/bitset.h"
12
13#ifndef FASTLED_DEFAULT_SLAB_SIZE
14#define FASTLED_DEFAULT_SLAB_SIZE 8
15#endif
16
17namespace fl {
18
19// Test hooks for malloc/free operations
20#if defined(FASTLED_TESTING)
21// Interface class for malloc/free test hooks
22class MallocFreeHook {
23public:
24 virtual ~MallocFreeHook() = default;
25 virtual void onMalloc(void* ptr, fl::size size) = 0;
26 virtual void onFree(void* ptr) = 0;
27};
28
29// Set test hooks for malloc and free operations
30void SetMallocFreeHook(MallocFreeHook* hook);
31
32// Clear test hooks (set to nullptr)
33void ClearMallocFreeHook();
34#endif
35
36void SetPSRamAllocator(void *(*alloc)(fl::size), void (*free)(void *));
37void *PSRamAllocate(fl::size size, bool zero = true);
38void PSRamDeallocate(void *ptr);
39void* Malloc(fl::size size);
40void Free(void *ptr);
41
42template <typename T> class PSRamAllocator {
43 public:
44 static T *Alloc(fl::size n) {
45 void *ptr = PSRamAllocate(sizeof(T) * n, true);
46 return fl::bit_cast_ptr<T>(ptr);
47 }
48
49 static void Free(T *p) {
50 if (p == nullptr) {
51 return;
52 }
54 }
55};
56
57// std compatible allocator.
58template <typename T> class allocator {
59 public:
60 // Type definitions required by STL
61 using value_type = T;
62 using pointer = T*;
63 using const_pointer = const T*;
64 using reference = T&;
65 using const_reference = const T&;
66 using size_type = fl::size;
68
69 // Rebind allocator to type U
70 template <typename U>
71 struct rebind {
73 };
74
75 // Default constructor
76 allocator() noexcept {}
77
78 // Copy constructor
79 template <typename U>
80 allocator(const allocator<U>&) noexcept {}
81
82 // Destructor
83 ~allocator() noexcept {}
84
85 // Use this to allocate large blocks of memory for T.
86 // This is useful for large arrays or objects that need to be allocated
87 // in a single block.
88 T* allocate(fl::size n) {
89 if (n == 0) {
90 return nullptr; // Handle zero allocation
91 }
92 fl::size size = sizeof(T) * n;
93 void *ptr = Malloc(size);
94 if (ptr == nullptr) {
95 return nullptr; // Handle allocation failure
96 }
97 fl::memfill(ptr, 0, sizeof(T) * n); // Zero-initialize the memory
98 return static_cast<T*>(ptr);
99 }
100
101 void deallocate(T* p, fl::size n) {
103 if (p == nullptr) {
104 return; // Handle null pointer
105 }
106 Free(p); // Free the allocated memory
107 }
108
109 // Construct an object at the specified address
110 template <typename U, typename... Args>
111 void construct(U* p, Args&&... args) {
112 if (p == nullptr) return;
113 new(static_cast<void*>(p)) U(fl::forward<Args>(args)...);
114 }
115
116 // Destroy an object at the specified address
117 template <typename U>
118 void destroy(U* p) {
119 if (p == nullptr) return;
120 p->~U();
121 }
122};
123
124template <typename T> class allocator_psram {
125 public:
126 // Type definitions required by STL
127 using value_type = T;
128 using pointer = T*;
129 using const_pointer = const T*;
130 using reference = T&;
131 using const_reference = const T&;
132 using size_type = fl::size;
134
135 // Rebind allocator to type U
136 template <typename U>
137 struct rebind {
139 };
140
141 // Default constructor
142 allocator_psram() noexcept {}
143
144 // Copy constructor
145 template <typename U>
147
148 // Destructor
149 ~allocator_psram() noexcept {}
150
151 // Allocate memory for n objects of type T
152 T* allocate(fl::size n) {
153 return PSRamAllocator<T>::Alloc(n);
154 }
155
156 // Deallocate memory for n objects of type T
157 void deallocate(T* p, fl::size n) {
160 }
161
162 // Construct an object at the specified address
163 template <typename U, typename... Args>
164 void construct(U* p, Args&&... args) {
165 if (p == nullptr) return;
166 new(static_cast<void*>(p)) U(fl::forward<Args>(args)...);
167 }
168
169 // Destroy an object at the specified address
170 template <typename U>
171 void destroy(U* p) {
172 if (p == nullptr) return;
173 p->~U();
174 }
175};
176
177
178
179// Slab allocator for fixed-size objects
180// Optimized for frequent allocation/deallocation of objects of the same size
181// Uses pre-allocated memory slabs with free lists to reduce fragmentation
182template <typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE>
184private:
185
186
187 static constexpr fl::size BLOCK_SIZE = sizeof(T) > sizeof(void*) ? sizeof(T) : sizeof(void*);
188 static constexpr fl::size BLOCKS_PER_SLAB = SLAB_SIZE;
189 static constexpr fl::size SLAB_MEMORY_SIZE = BLOCK_SIZE * BLOCKS_PER_SLAB;
190
191 struct Slab {
195 fl::bitset_fixed<BLOCKS_PER_SLAB> allocated_blocks; // Track which blocks are allocated
196
197 Slab() : next(nullptr), memory(nullptr), allocated_count(0) {}
198
200 if (memory) {
201 free(memory);
202 }
203 }
204 };
205
209
211 Slab* slab = static_cast<Slab*>(malloc(sizeof(Slab)));
212 if (!slab) {
213 return nullptr;
214 }
215
216 // Use placement new to properly initialize the Slab
217 new(slab) Slab();
218
219 slab->memory = static_cast<u8*>(malloc(SLAB_MEMORY_SIZE));
220 if (!slab->memory) {
221 slab->~Slab();
222 free(slab);
223 return nullptr;
224 }
225
226 // Initialize all blocks in the slab as free
227 slab->allocated_blocks.reset(); // All blocks start as free
228
229 // Add slab to the slab list
230 slab->next = slabs_;
231 slabs_ = slab;
232
233 return slab;
234 }
235
236 void* allocateFromSlab(fl::size n = 1) {
237 // Try to find n contiguous free blocks in existing slabs
238 for (Slab* slab = slabs_; slab; slab = slab->next) {
239 void* ptr = findContiguousBlocks(slab, n);
240 if (ptr) {
241 return ptr;
242 }
243 }
244
245 // No contiguous blocks found, create new slab if n fits
246 if (n <= BLOCKS_PER_SLAB) {
247 if (!createSlab()) {
248 return nullptr; // Out of memory
249 }
250
251 // Try again with the new slab
252 return findContiguousBlocks(slabs_, n);
253 }
254
255 // Request too large for slab, fall back to malloc
256 return nullptr;
257 }
258
259
260
261 void* findContiguousBlocks(Slab* slab, fl::size n) {
262 // Check if allocation is too large for this slab
263 if (n > BLOCKS_PER_SLAB) {
264 return nullptr;
265 }
266
267 // Use bitset's find_run to find n contiguous free blocks (false = free)
268 fl::i32 start = slab->allocated_blocks.find_run(false, static_cast<fl::u32>(n));
269 if (start >= 0) {
270 // Mark blocks as allocated
271 for (fl::size i = 0; i < n; ++i) {
272 slab->allocated_blocks.set(static_cast<fl::u32>(start + i), true);
273 }
274 slab->allocated_count += n;
275 total_allocated_ += n;
276
277 // Return pointer to the first block
278 return slab->memory + static_cast<fl::size>(start) * BLOCK_SIZE;
279 }
280
281 return nullptr;
282 }
283
284 void deallocateToSlab(void* ptr, fl::size n = 1) {
285 if (!ptr) {
286 return;
287 }
288
289 // Find which slab this block belongs to
290 for (Slab* slab = slabs_; slab; slab = slab->next) {
291 u8* slab_start = slab->memory;
292 u8* slab_end = slab_start + SLAB_MEMORY_SIZE;
293 u8* block_ptr = fl::bit_cast_ptr<u8>(ptr);
294
295 if (block_ptr >= slab_start && block_ptr < slab_end) {
296 fl::size block_index = (block_ptr - slab_start) / BLOCK_SIZE;
297
298 // Mark blocks as free in the bitset
299 for (fl::size i = 0; i < n; ++i) {
300 if (block_index + i < BLOCKS_PER_SLAB) {
301 slab->allocated_blocks.set(block_index + i, false);
302 }
303 }
304
305 slab->allocated_count -= n;
307 break;
308 }
309 }
310 }
311
312public:
313 // Constructor
315
316 // Destructor
318 cleanup();
319 }
320
321 // Non-copyable
322 SlabAllocator(const SlabAllocator&) = delete;
324
325 // Movable
326 SlabAllocator(SlabAllocator&& other) noexcept
327 : slabs_(other.slabs_), total_allocated_(other.total_allocated_), total_deallocated_(other.total_deallocated_) {
328 other.slabs_ = nullptr;
329 other.total_allocated_ = 0;
330 other.total_deallocated_ = 0;
331 }
332
334 if (this != &other) {
335 cleanup();
336 slabs_ = other.slabs_;
337 total_allocated_ = other.total_allocated_;
338 total_deallocated_ = other.total_deallocated_;
339 other.slabs_ = nullptr;
340 other.total_allocated_ = 0;
341 other.total_deallocated_ = 0;
342 }
343 return *this;
344 }
345
346 T* allocate(fl::size n = 1) {
347 if (n == 0) {
348 return nullptr;
349 }
350
351 // Try to allocate from slab first
352 void* ptr = allocateFromSlab(n);
353 if (ptr) {
354 fl::memfill(ptr, 0, sizeof(T) * n);
355 return static_cast<T*>(ptr);
356 }
357
358 // Fall back to regular malloc for large allocations
359 ptr = malloc(sizeof(T) * n);
360 if (ptr) {
361 fl::memfill(ptr, 0, sizeof(T) * n);
362 }
363 return static_cast<T*>(ptr);
364 }
365
366 void deallocate(T* ptr, fl::size n = 1) {
367 if (!ptr) {
368 return;
369 }
370
371 // Try to deallocate from slab first
372 bool found_in_slab = false;
373 for (Slab* slab = slabs_; slab; slab = slab->next) {
374 u8* slab_start = slab->memory;
375 u8* slab_end = slab_start + SLAB_MEMORY_SIZE;
376 u8* block_ptr = fl::bit_cast_ptr<u8>(static_cast<void*>(ptr));
377
378 if (block_ptr >= slab_start && block_ptr < slab_end) {
379 deallocateToSlab(ptr, n);
380 found_in_slab = true;
381 break;
382 }
383 }
384
385 if (!found_in_slab) {
386 // This was allocated with regular malloc
387 free(ptr);
388 }
389 }
390
391 // Get allocation statistics
392 fl::size getTotalAllocated() const { return total_allocated_; }
393 fl::size getTotalDeallocated() const { return total_deallocated_; }
395
396 // Get number of slabs
397 fl::size getSlabCount() const {
398 fl::size count = 0;
399 for (Slab* slab = slabs_; slab; slab = slab->next) {
400 ++count;
401 }
402 return count;
403 }
404
405 // Cleanup all slabs
406 void cleanup() {
407 while (slabs_) {
408 Slab* next = slabs_->next;
409 slabs_->~Slab();
410 free(slabs_);
411 slabs_ = next;
412 }
415 }
416};
417
418// STL-compatible slab allocator
419template <typename T, fl::size SLAB_SIZE = FASTLED_DEFAULT_SLAB_SIZE>
421public:
422 // Type definitions required by STL
423 using value_type = T;
424 using pointer = T*;
425 using const_pointer = const T*;
426 using reference = T&;
427 using const_reference = const T&;
428 using size_type = fl::size;
430
431 // Rebind allocator to type U
432 template <typename U>
440
441 // Default constructor
442 allocator_slab() noexcept {}
443
444 // Copy constructor
445 allocator_slab(const allocator_slab& other) noexcept {
446 FASTLED_UNUSED(other);
447 }
448
449 // Copy assignment
450 allocator_slab& operator=(const allocator_slab& other) noexcept {
451 FASTLED_UNUSED(other);
452 return *this;
453 }
454
455 // Template copy constructor
456 template <typename U>
458 FASTLED_UNUSED(other);
459 }
460
461 // Destructor
462 ~allocator_slab() noexcept {}
463
464private:
465 // Get the shared static allocator instance
470
471public:
472 // Allocate memory for n objects of type T
473 T* allocate(fl::size n) {
474 // Use a static allocator instance per type/size combination
476 return allocator.allocate(n);
477 }
478
479 // Deallocate memory for n objects of type T
480 void deallocate(T* p, fl::size n) {
481 // Use the same static allocator instance
483 allocator.deallocate(p, n);
484 }
485
486 // Construct an object at the specified address
487 template <typename U, typename... Args>
488 void construct(U* p, Args&&... args) {
489 if (p == nullptr) return;
490 new(static_cast<void*>(p)) U(fl::forward<Args>(args)...);
491 }
492
493 // Destroy an object at the specified address
494 template <typename U>
495 void destroy(U* p) {
496 if (p == nullptr) return;
497 p->~U();
498 }
499
500 // Cleanup method to clean up the static slab allocator
501 void cleanup() {
502 // Access the same static allocator instance and clean it up
504 allocator.cleanup();
505 }
506
507 // Equality comparison
508 bool operator==(const allocator_slab& other) const noexcept {
509 FASTLED_UNUSED(other);
510 return true; // All instances are equivalent
511 }
512
513 bool operator!=(const allocator_slab& other) const noexcept {
514 return !(*this == other);
515 }
516};
517
518// Inlined allocator that stores the first N elements inline
519// Falls back to the base allocator for additional elements
520template <typename T, fl::size N, typename BaseAllocator = fl::allocator<T>>
522private:
523
524 // Inlined storage block
526 alignas(T) u8 data[N * sizeof(T)];
527
529 fl::memfill(data, 0, sizeof(data));
530 }
531 };
532
533 InlinedStorage m_inlined_storage;
534 BaseAllocator m_base_allocator;
535 fl::size m_inlined_used = 0;
536 fl::bitset_fixed<N> m_free_bits; // Track free slots for inlined memory only
537 fl::size m_active_allocations = 0; // Track current active allocations
538
539public:
540 // Type definitions required by STL
541 using value_type = T;
542 using pointer = T*;
543 using const_pointer = const T*;
544 using reference = T&;
545 using const_reference = const T&;
546 using size_type = fl::size;
548
549 // Rebind allocator to type U
550 template <typename U>
554
555 // Default constructor
556 allocator_inlined() noexcept = default;
557
558 // Copy constructor
559 allocator_inlined(const allocator_inlined& other) noexcept {
560 // Copy inlined data
561 m_inlined_used = other.m_inlined_used;
562 for (fl::size i = 0; i < m_inlined_used; ++i) {
563 new (&get_inlined_ptr()[i]) T(other.get_inlined_ptr()[i]);
564 }
565
566 // Copy free bits
567 m_free_bits = other.m_free_bits;
568
569 // Note: Heap allocations are not copied, only inlined data
570
571 // Copy active allocations count
572 m_active_allocations = other.m_active_allocations;
573 }
574
575 // Copy assignment
577 if (this != &other) {
578 clear();
579
580 // Copy inlined data
581 m_inlined_used = other.m_inlined_used;
582 for (fl::size i = 0; i < m_inlined_used; ++i) {
583 new (&get_inlined_ptr()[i]) T(other.get_inlined_ptr()[i]);
584 }
585
586 // Copy free bits
587 m_free_bits = other.m_free_bits;
588
589 // Note: Heap allocations are not copied, only inlined data
590
591 // Copy active allocations count
592 m_active_allocations = other.m_active_allocations;
593 }
594 return *this;
595 }
596
597 // Template copy constructor
598 template <typename U>
599 allocator_inlined(const allocator_inlined<U, N, typename BaseAllocator::template rebind<U>::other>& other) noexcept {
600 FASTLED_UNUSED(other);
601 }
602
603 // Destructor
605 clear();
606 }
607
608 // Allocate memory for n objects of type T
609 T* allocate(fl::size n) {
610 if (n == 0) {
611 return nullptr;
612 }
613
614 // For large allocations (n > 1), use base allocator directly
615 if (n > 1) {
616 T* ptr = m_base_allocator.allocate(n);
617 if (ptr) {
619 }
620 return ptr;
621 }
622
623 // For single allocations, first try inlined memory
624 // Find first free inlined slot
625 fl::i32 free_slot = m_free_bits.find_first(false);
626 if (free_slot >= 0 && static_cast<fl::size>(free_slot) < N) {
627 // Mark the inlined slot as used
628 m_free_bits.set(static_cast<fl::u32>(free_slot), true);
629
630 // Update inlined usage tracking
631 if (static_cast<fl::size>(free_slot) + 1 > m_inlined_used) {
632 m_inlined_used = static_cast<fl::size>(free_slot) + 1;
633 }
635 return &get_inlined_ptr()[static_cast<fl::size>(free_slot)];
636 }
637
638 // No inlined slots available, use heap allocation
639 T* ptr = m_base_allocator.allocate(1);
640 if (ptr) {
642 }
643 return ptr;
644 }
645
646 // Deallocate memory for n objects of type T
647 void deallocate(T* p, fl::size n) {
648 if (!p || n == 0) {
649 return;
650 }
651
652 // Check if this is inlined memory
653 T* inlined_start = get_inlined_ptr();
654 T* inlined_end = inlined_start + N;
655
656 if (p >= inlined_start && p < inlined_end) {
657 // This is inlined memory, mark slots as free
658 fl::size slot_index = (p - inlined_start);
659 for (fl::size i = 0; i < n; ++i) {
660 if (slot_index + i < N) {
661 m_free_bits.set(slot_index + i, false); // Mark as free
662 }
663 }
665 return;
666 }
667
668
669
670 // Fallback to base allocator for heap allocations
671 m_base_allocator.deallocate(p, n);
673 }
674
675 // Construct an object at the specified address
676 template <typename U, typename... Args>
677 void construct(U* p, Args&&... args) {
678 if (p == nullptr) return;
679 new(static_cast<void*>(p)) U(fl::forward<Args>(args)...);
680 }
681
682 // Destroy an object at the specified address
683 template <typename U>
684 void destroy(U* p) {
685 if (p == nullptr) return;
686 p->~U();
687 }
688
689 // Clear all allocated memory
690 void clear() {
691 // Destroy inlined objects
692 for (fl::size i = 0; i < m_inlined_used; ++i) {
693 get_inlined_ptr()[i].~T();
694 }
695 m_inlined_used = 0;
696 m_free_bits.reset();
698
699 // Clean up the base allocator (for SlabAllocator, this clears slabs and free lists)
701 }
702
703 // Get total allocated size
704 fl::size total_size() const {
706 }
707
708 // Get inlined capacity
709 fl::size inlined_capacity() const {
710 return N;
711 }
712
713 // Check if using inlined storage
714 bool is_using_inlined() const {
716 }
717
718private:
720 return reinterpret_cast<T*>(m_inlined_storage.data);
721 }
722
723 const T* get_inlined_ptr() const {
724 return reinterpret_cast<const T*>(m_inlined_storage.data);
725 }
726
727 // SFINAE helper to detect if base allocator has cleanup() method
728 template<typename U>
729 static auto has_cleanup_impl(int) -> decltype(fl::declval<U>().cleanup(), fl::true_type{});
730
731 template<typename U>
733
735
736 // Call cleanup on base allocator if it has the method
740
744
746 // Base allocator doesn't have cleanup method, do nothing
747 }
748
749
750
751 // Equality comparison
752 bool operator==(const allocator_inlined& other) const noexcept {
753 FASTLED_UNUSED(other);
754 return true; // All instances are equivalent for now
755 }
756
757 bool operator!=(const allocator_inlined& other) const noexcept {
758 return !(*this == other);
759 }
760};
761
762// Inlined allocator that uses PSRam for heap allocation
763template <typename T, fl::size N>
765
766// Inlined allocator that uses slab allocator for heap allocation
767template <typename T, fl::size N, fl::size SLAB_SIZE = 8>
769
770
771template <typename T, fl::size N>
773
774} // namespace fl
static T * Alloc(fl::size n)
Definition allocator.h:44
static void Free(T *p)
Definition allocator.h:49
static constexpr fl::size BLOCK_SIZE
Definition allocator.h:187
fl::size getTotalDeallocated() const
Definition allocator.h:393
static constexpr fl::size BLOCKS_PER_SLAB
Definition allocator.h:188
SlabAllocator & operator=(const SlabAllocator &)=delete
void deallocate(T *ptr, fl::size n=1)
Definition allocator.h:366
fl::size total_allocated_
Definition allocator.h:207
SlabAllocator(const SlabAllocator &)=delete
void * allocateFromSlab(fl::size n=1)
Definition allocator.h:236
fl::size getTotalAllocated() const
Definition allocator.h:392
static constexpr fl::size SLAB_MEMORY_SIZE
Definition allocator.h:189
T * allocate(fl::size n=1)
Definition allocator.h:346
SlabAllocator(SlabAllocator &&other) noexcept
Definition allocator.h:326
fl::size getSlabCount() const
Definition allocator.h:397
void * findContiguousBlocks(Slab *slab, fl::size n)
Definition allocator.h:261
fl::size total_deallocated_
Definition allocator.h:208
SlabAllocator & operator=(SlabAllocator &&other) noexcept
Definition allocator.h:333
void deallocateToSlab(void *ptr, fl::size n=1)
Definition allocator.h:284
Slab * createSlab()
Definition allocator.h:210
fl::size getActiveAllocations() const
Definition allocator.h:394
allocator_inlined() noexcept=default
bool is_using_inlined() const
Definition allocator.h:714
allocator_inlined & operator=(const allocator_inlined &other) noexcept
Definition allocator.h:576
void cleanup_base_allocator_impl(fl::true_type)
Definition allocator.h:741
void cleanup_base_allocator()
Definition allocator.h:737
void deallocate(T *p, fl::size n)
Definition allocator.h:647
fl::size total_size() const
Definition allocator.h:704
static auto has_cleanup_impl(int) -> decltype(fl::declval< U >().cleanup(), fl::true_type{})
~allocator_inlined() noexcept
Definition allocator.h:604
allocator_inlined(const allocator_inlined< U, N, typename BaseAllocator::template rebind< U >::other > &other) noexcept
Definition allocator.h:599
T * allocate(fl::size n)
Definition allocator.h:609
bool operator!=(const allocator_inlined &other) const noexcept
Definition allocator.h:757
void construct(U *p, Args &&... args)
Definition allocator.h:677
const T & const_reference
Definition allocator.h:545
ptrdiff_t difference_type
Definition allocator.h:547
static fl::false_type has_cleanup_impl(...)
const T * const_pointer
Definition allocator.h:543
void cleanup_base_allocator_impl(fl::false_type)
Definition allocator.h:745
bool operator==(const allocator_inlined &other) const noexcept
Definition allocator.h:752
fl::size inlined_capacity() const
Definition allocator.h:709
const T * get_inlined_ptr() const
Definition allocator.h:723
allocator_inlined< U, N, typename BaseAllocator::template rebind< U >::other > other
Definition allocator.h:552
ptrdiff_t difference_type
Definition allocator.h:133
T * allocate(fl::size n)
Definition allocator.h:152
void construct(U *p, Args &&... args)
Definition allocator.h:164
allocator_psram(const allocator_psram< U > &) noexcept
Definition allocator.h:146
const T & const_reference
Definition allocator.h:131
const T * const_pointer
Definition allocator.h:129
void destroy(U *p)
Definition allocator.h:171
allocator_psram() noexcept
Definition allocator.h:142
void deallocate(T *p, fl::size n)
Definition allocator.h:157
~allocator_psram() noexcept
Definition allocator.h:149
allocator_psram< U > other
Definition allocator.h:138
const T * const_pointer
Definition allocator.h:425
allocator_slab(const allocator_slab &other) noexcept
Definition allocator.h:445
void destroy(U *p)
Definition allocator.h:495
T * allocate(fl::size n)
Definition allocator.h:473
const T & const_reference
Definition allocator.h:427
void deallocate(T *p, fl::size n)
Definition allocator.h:480
allocator_slab(const allocator_slab< U, SLAB_SIZE > &other) noexcept
Definition allocator.h:457
~allocator_slab() noexcept
Definition allocator.h:462
allocator_slab() noexcept
Definition allocator.h:442
static SlabAllocator< T, SLAB_SIZE > & get_allocator()
Definition allocator.h:466
bool operator!=(const allocator_slab &other) const noexcept
Definition allocator.h:513
void construct(U *p, Args &&... args)
Definition allocator.h:488
ptrdiff_t difference_type
Definition allocator.h:429
bool operator==(const allocator_slab &other) const noexcept
Definition allocator.h:508
allocator_slab & operator=(const allocator_slab &other) noexcept
Definition allocator.h:450
typename fl::conditional< fl::is_same< U, void >::value, allocator_slab< char, SLAB_SIZE >, allocator_slab< U, SLAB_SIZE > >::type other
Definition allocator.h:434
const T * const_pointer
Definition allocator.h:63
ptrdiff_t difference_type
Definition allocator.h:67
allocator() noexcept
Definition allocator.h:76
void construct(U *p, Args &&... args)
Definition allocator.h:111
allocator(const allocator< U > &) noexcept
Definition allocator.h:80
T * allocate(fl::size n)
Definition allocator.h:88
fl::size size_type
Definition allocator.h:66
void destroy(U *p)
Definition allocator.h:118
const T & const_reference
Definition allocator.h:65
~allocator() noexcept
Definition allocator.h:83
void deallocate(T *p, fl::size n)
Definition allocator.h:101
allocator< U > other
Definition allocator.h:72
void Free(void *ptr)
unsigned char u8
Definition int.h:17
To * bit_cast_ptr(void *storage) noexcept
Definition bit_cast.h:54
__PTRDIFF_TYPE__ ptrdiff_t
Definition cstddef.h:22
integral_constant< bool, false > false_type
Definition type_traits.h:30
void * memfill(void *ptr, int value, fl::size num)
Definition memfill.h:11
add_rvalue_reference< T >::type declval() noexcept
void SetPSRamAllocator(void *(*alloc)(fl::size), void(*free)(void *))
Definition allocator.cpp:72
void PSRamDeallocate(void *ptr)
Definition allocator.cpp:96
void * Malloc(fl::size size)
allocator_inlined< T, N, fl::allocator_slab< T > > allocator_inlined_slab
Definition allocator.h:772
void * PSRamAllocate(fl::size size, bool zero)
Definition allocator.cpp:77
integral_constant< bool, true > true_type
Definition type_traits.h:29
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
allocator_inlined< T, N, fl::allocator_slab< T, SLAB_SIZE > > allocator_inlined_slab_psram
Definition allocator.h:768
allocator_inlined< T, N, fl::allocator_psram< T > > allocator_inlined_psram
Definition allocator.h:764
IMPORTANT!
Definition crgb.h:20
corkscrew_args args
Definition old.h:150
fl::bitset_fixed< BLOCKS_PER_SLAB > allocated_blocks
Definition allocator.h:195
static constexpr bool value
Definition type_traits.h:84
#define FASTLED_UNUSED(x)
Definition unused.h:4