FastLED 3.10.8
Loading...
Searching...
No Matches
shared_ptr.h
Go to the documentation of this file.
1#pragma once
2
5#include "fl/stl/cstddef.h"
6#include "fl/stl/bit_cast.h"
7#include "fl/stl/atomic.h"
8#include "fl/stl/int.h"
9#include "fl/stl/align.h"
10#include "fl/stl/cstdlib.h"
11#include "fl/stl/noexcept.h"
12
13
14namespace fl {
15
16// Forward declarations
17template<typename T> class shared_ptr; // IWYU pragma: keep
18template<typename T> class weak_ptr;
19
20namespace adl_barrier { // see fl/stl/adl_barrier.h
21template<typename T, typename... Args>
22shared_ptr<T> make_shared(Args&&... args) FL_NO_EXCEPT;
23template<typename T, typename A, typename... Args>
24shared_ptr<T> allocate_shared(const A& alloc, Args&&... args) FL_NO_EXCEPT;
25} // namespace adl_barrier
26
27namespace detail {
28
29// Tag type for make_shared constructor
31
32// No-tracking tag for make_shared_no_tracking
34
35// Enhanced control block structure with no-tracking support using special value
39
40 // Special value indicating no-tracking mode
41 static constexpr fl::u32 NO_TRACKING_VALUE = 0xffffffff;
42
43 ControlBlockBase(bool track = true) FL_NO_EXCEPT
44 : shared_count(track ? 1 : NO_TRACKING_VALUE), weak_count(1) {}
45 // Destructor defined out-of-line in shared_ptr.cpp.hpp to anchor vtable
46 // to a single translation unit, preventing ODR violations when using shared libraries.
48 virtual void destroy_object() FL_NO_EXCEPT = 0;
50
51 // Reference counting functions - defined out-of-line in shared_ptr.cpp.hpp
52 // to prevent UBSAN vptr mismatch errors when objects cross shared library boundaries.
53 // When these are inline, different binaries get different vtables, and UBSAN
54 // detects the mismatch when checking member access.
57
58 // Check if this control block is in no-tracking mode
59 bool is_no_tracking() const FL_NO_EXCEPT;
60};
61
62// Default deleter implementation
63template<typename T>
65 void operator()(T* ptr) const FL_NO_EXCEPT {
66 delete ptr;
67 }
68};
69
70// Deleter that does nothing (for stack/static objects)
71template<typename T>
73 void operator()(T*) const FL_NO_EXCEPT {
74 // Intentionally do nothing - object lifetime managed externally
75 }
76};
77
78// Array deleter implementation for delete[]
79template<typename T>
81 void operator()(T* ptr) const FL_NO_EXCEPT {
82 delete[] ptr;
83 }
84};
85
86// Enhanced control block for external objects with no-tracking support
87template<typename T, typename Deleter = default_delete<T>>
89 T* ptr;
90 Deleter deleter;
91
92 ControlBlock(T* p, Deleter d = Deleter(), bool track = true) FL_NO_EXCEPT
93 : ControlBlockBase(track), ptr(p), deleter(d) {}
94
95 void destroy_object() FL_NO_EXCEPT override {
96 if (ptr && !is_no_tracking()) { // Only delete if tracking
97 deleter(ptr);
98 ptr = nullptr;
99 }
100 }
101
103 delete this;
104 }
105};
106
107// Helper to compute maximum alignment for InlinedControlBlock
108// Ensures alignment is at least as strict as ControlBlockBase, but respects T's requirements if larger
109template<typename T>
111 static constexpr fl::size value =
112 (alignof(T) > alignof(ControlBlockBase)) ? alignof(T) : alignof(ControlBlockBase);
113};
114
115// Inlined control block for make_shared optimization
116// Stores the object inline with the control block (single allocation)
117template<typename T>
118struct FL_ALIGNAS(control_block_alignment<T>::value) InlinedControlBlock : public ControlBlockBase {
119 FL_ALIGNAS(T) char storage[sizeof(T)]; // Object storage (properly aligned)
120 bool object_constructed; // Track construction state
121
122 InlinedControlBlock() FL_NO_EXCEPT
123 : ControlBlockBase(true), object_constructed(false) {}
124
125 // Aligned operator new/delete: when T has alignment > default new alignment
126 // (e.g. FL_ALIGNAS(64)), plain `new` won't honour it on pre-C++17 compilers.
127 // GCC emits -Waligned-new in that case. These overrides route through
128 // fl::aligned_alloc / fl::aligned_free so the block is always properly aligned.
129 static void* operator new(fl::size_t size) FL_NO_EXCEPT {
130 constexpr fl::size_t align = control_block_alignment<T>::value;
131 return fl::aligned_alloc(align, size);
132 }
133 static void operator delete(void* ptr) {
134 fl::aligned_free(ptr);
135 }
136
137 // Get pointer to the inline object storage
138 T* get_object() FL_NO_EXCEPT {
139 return fl::bit_cast<T*>(&storage[0]);
140 }
141
142 const T* get_object() const FL_NO_EXCEPT {
143 return fl::bit_cast<const T*>(&storage[0]);
144 }
145
146 void destroy_object() FL_NO_EXCEPT override {
147 if (object_constructed) {
148 get_object()->~T(); // Manual destructor call
149 object_constructed = false;
150 }
151 }
152
153 void destroy_control_block() FL_NO_EXCEPT override {
154 delete this;
155 }
156};
157
158
159} // namespace detail
160
161// std::shared_ptr compatible implementation
162template<typename T>
164private:
167
168 // Internal constructor for make_shared and weak_ptr conversion
170 : mPtr(ptr), mControlBlock(control_block) {
171 // Control block was created with reference count 1, no need to increment
172 }
173
174 // Internal constructor for no-tracking (control_block should be nullptr)
176 : mPtr(ptr), mControlBlock(control_block) {
177 // No control block - this is a zero-overhead wrapper around a raw pointer
178 }
179
180 // void release() {
181 // if (mControlBlock) {
182 // if (mControlBlock->remove_shared_ref()) {
183 // mControlBlock->destroy_object();
184 // if (--mControlBlock->weak_count == 0) {
185 // mControlBlock->destroy_control_block();
186 // }
187 // }
188 // }
189 // }
190
192 if (mControlBlock) {
193 mControlBlock->add_shared_ref();
194 }
195 }
196
197public:
198 using element_type = T;
200
201 // Default constructor
202 shared_ptr() FL_NO_EXCEPT : mPtr(nullptr), mControlBlock(nullptr) {}
204
205
206
207 // Copy constructor
208 shared_ptr(const shared_ptr& other) FL_NO_EXCEPT : mPtr(other.mPtr), mControlBlock(other.mControlBlock) {
209 acquire();
210 }
211
212 // Converting copy constructor (allows upcasting: shared_ptr<Derived> → shared_ptr<Base>)
213 template<typename Y, typename = typename fl::enable_if<fl::is_base_of<T, Y>::value>::type>
214 shared_ptr(const shared_ptr<Y>& other) FL_NO_EXCEPT : mPtr(static_cast<T*>(other.mPtr)), mControlBlock(other.mControlBlock) {
215 acquire();
216 }
217
218 // Move constructor
219 shared_ptr(shared_ptr&& other) FL_NO_EXCEPT : mPtr(other.mPtr), mControlBlock(other.mControlBlock) {
220 other.mPtr = nullptr;
221 other.mControlBlock = nullptr;
222 }
223
224 // Converting move constructor (allows upcasting: shared_ptr<Derived> → shared_ptr<Base>)
225 template<typename Y, typename = typename fl::enable_if<fl::is_base_of<T, Y>::value>::type>
226 shared_ptr(shared_ptr<Y>&& other) FL_NO_EXCEPT : mPtr(static_cast<T*>(other.mPtr)), mControlBlock(other.mControlBlock) {
227 other.mPtr = nullptr;
228 other.mControlBlock = nullptr;
229 }
230
231 // Constructor from weak_ptr
232 template<typename Y>
233 explicit shared_ptr(const weak_ptr<Y>& weak) FL_NO_EXCEPT;
234
235 // Aliasing constructor (C++11 standard §20.7.2.2.1)
236 // Shares ownership with 'other' but stores 'ptr'
237 // Used by pointer cast functions (static_pointer_cast, etc.)
238 template<typename Y>
240 : mPtr(ptr), mControlBlock(other.mControlBlock) {
241 acquire();
242 }
243
244 // Destructor
246 //FL_WARN("shared_ptr destructor called, mPtr=" << mPtr
247 // << ", mControlBlock=" << mControlBlock);
248 reset();
249 }
250
251 // Assignment operators
253 if (this != &other) {
254 reset();
255 mPtr = other.mPtr;
256 mControlBlock = other.mControlBlock;
257 acquire();
258 }
259 return *this;
260 }
261
262 // Converting copy assignment (allows upcasting: shared_ptr<Derived> → shared_ptr<Base>)
263 template<typename Y, typename = typename fl::enable_if<fl::is_base_of<T, Y>::value>::type>
265 reset();
266 mPtr = static_cast<T*>(other.mPtr);
267 mControlBlock = other.mControlBlock;
268 acquire();
269 return *this;
270 }
271
273 if (this != &other) {
274 this->swap(other);
275 other.reset();
276 }
277 return *this;
278 }
279
280 // Converting move assignment (allows upcasting: shared_ptr<Derived> → shared_ptr<Base>)
281 template<typename Y, typename = typename fl::enable_if<fl::is_base_of<T, Y>::value>::type>
283 if (static_cast<void*>(this) != static_cast<void*>(&other)) {
284 reset();
285 mPtr = static_cast<T*>(other.mPtr);
286 mControlBlock = other.mControlBlock;
287 other.mPtr = nullptr;
288 other.mControlBlock = nullptr;
289 }
290 return *this;
291 }
292
293 // Modifiers
295 //FL_WARN("shared_ptr::reset() called: mPtr=" << mPtr
296 // << ", mControlBlock=" << mControlBlock);
297 if (mControlBlock) {
298 //FL_WARN("control_block exists, calling remove_shared_ref()");
299 if (mControlBlock->remove_shared_ref()) {
300 //FL_WARN("mControlBlock->remove_shared_ref() returned true, destroying object");
301 mControlBlock->destroy_object();
302 if (--mControlBlock->weak_count == 0) {
303 //FL_WARN("weak_count reached 0, destroying control block");
304 mControlBlock->destroy_control_block();
305 }
306 }
307 }
308 mPtr = nullptr;
309 mControlBlock = nullptr;
310 }
311
313 this->swap(other);
314 other.reset();
315 }
316
318 fl::swap(mPtr, other.mPtr);
319 fl::swap(mControlBlock, other.mControlBlock);
320 }
321
323 fl::swap(mPtr, other.mPtr);
324 fl::swap(mControlBlock, other.mControlBlock);
325 }
326
327
328
329 // template<typename Y>
330 // void reset(Y* ptr) {
331 // shared_ptr(ptr).swap(*this);
332 // }
333
334 // template<typename Y, typename Deleter>
335 // void reset(Y* ptr, Deleter d) {
336 // shared_ptr(ptr, d).swap(*this);
337 // }
338
339
340
341 // Observers
342 T* get() const FL_NO_EXCEPT { return mPtr; }
343
344 T& operator*() const FL_NO_EXCEPT { return *mPtr; }
345 T* operator->() const FL_NO_EXCEPT { return mPtr; }
346
347 T& operator[](ptrdiff_t idx) const FL_NO_EXCEPT { return mPtr[idx]; }
348
349 // NEW: use_count returns 0 for no-tracking shared_ptrs
350 long use_count() const FL_NO_EXCEPT {
351 if (!mControlBlock) return 0;
353 return 0;
354 }
355 return static_cast<long>(mControlBlock->shared_count);
356 }
357
358 bool unique() const FL_NO_EXCEPT { return use_count() == 1; }
359
360 explicit operator bool() const FL_NO_EXCEPT { return mPtr != nullptr; }
361
362 // NEW: Check if this is a no-tracking shared_ptr
364 return mControlBlock && mControlBlock->is_no_tracking();
365 }
366
367 // Comparison operators for nullptr only (to avoid ambiguity with non-member operators)
368
370 return mPtr == nullptr;
371 }
372
374 return mPtr != nullptr;
375 }
376
377private:
378
379 // Constructor from raw pointer with default deleter
380 template<typename Y>
381 explicit shared_ptr(Y* ptr) FL_NO_EXCEPT : mPtr(ptr) {
382 if (mPtr) {
384 } else {
385 mControlBlock = nullptr;
386 }
387 }
388
389 // Constructor from raw pointer with custom deleter
390 template<typename Y, typename Deleter>
391 shared_ptr(Y* ptr, Deleter d) FL_NO_EXCEPT : mPtr(ptr) {
392 if (mPtr) {
394 } else {
395 mControlBlock = nullptr;
396 }
397 }
398
399 template<typename Y> friend class shared_ptr;
400 template<typename Y> friend class weak_ptr;
401
402 template<typename Y, typename... Args>
404
405 template<typename Y, typename Deleter, typename... Args>
407
408 template<typename Y, typename A, typename... Args>
410
411 template<typename Y>
413
414 template<typename Y>
416};
417
418// Factory functions
419
420namespace adl_barrier { // see fl/stl/adl_barrier.h
421// make_shared with optimized inlined storage (single allocation)
422template<typename T, typename... Args>
424 // Allocate the control block's raw memory explicitly and null-check it
425 // BEFORE constructing. `new detail::InlinedControlBlock<T>()` cannot be
426 // trusted to skip construction on allocation failure: its custom
427 // operator new returns null under OOM, but the new-expression still
428 // runs the constructor on that null pointer — writing through address 0
429 // (EXCVADDR 0 crash) — and the old `if (control == nullptr)` guard was
430 // dead code because it ran only AFTER the null construction. This was
431 // the primary FastLED#3588 corruptor: under low free heap (which an
432 // active WiFi SoftAP creates, but so does any memory pressure) every
433 // make_shared<json_value> in the JSON-RPC build path faulted. Separate
434 // allocation from construction so the null check actually protects it.
435 void* mem = detail::InlinedControlBlock<T>::operator new(
436 sizeof(detail::InlinedControlBlock<T>));
437 if (mem == nullptr) {
438 return shared_ptr<T>(); // OOM — degrade to an empty shared_ptr
439 }
440 auto* control = ::new (mem) detail::InlinedControlBlock<T>(); // global placement new on valid memory
441 T* obj = control->get_object();
442 new(obj) T(fl::forward<Args>(args)...); // Placement new
443 control->object_constructed = true;
444 return shared_ptr<T>(obj, control, detail::make_shared_tag{});
445}
446} // namespace adl_barrier
447
448template<typename T, typename Deleter, typename... Args>
450 T* obj = new T(fl::forward<Args>(args)...);
451 if (obj == nullptr) {
452 return shared_ptr<T>(); // OOM — see make_shared
453 }
454 auto* control = new detail::ControlBlock<T, Deleter>(obj, d);
455 if (control == nullptr) {
456 d(obj);
457 return shared_ptr<T>(); // OOM — see make_shared
458 }
459 //new(control->get_object()) T(fl::forward<Args>(args)...);
460 //control->object_constructed = true;
461 return shared_ptr<T>(obj, control, detail::make_shared_tag{});
462}
463
464// NEW: Creates a shared_ptr that does not modify the reference count
465// The shared_ptr and any copies will not affect object lifetime.
466// No control block is allocated - this is a zero-overhead wrapper around a raw pointer.
467template<typename T>
471
472// make_shared_array for array allocations
473template<typename T>
475 T* arr = new T[n](); // Zero-initialize the array
476 if (arr == nullptr) {
477 return shared_ptr<T>(); // OOM — see make_shared
478 }
480 if (control == nullptr) {
481 delete[] arr;
482 return shared_ptr<T>(); // OOM — see make_shared
483 }
484 return shared_ptr<T>(arr, control, detail::make_shared_tag{});
485}
486
487namespace adl_barrier { // see fl/stl/adl_barrier.h
488// allocate_shared (simplified version without full allocator support for now)
489template<typename T, typename A, typename... Args>
490shared_ptr<T> allocate_shared(const A& /* alloc */, Args&&... args) FL_NO_EXCEPT {
491 // For now, just delegate to make_shared
492 // Full allocator support would require more complex control block management
494}
495} // namespace adl_barrier
496
497// Non-member comparison operators
498template<typename T, typename Y>
500 return lhs.get() == rhs.get();
501}
502
503template<typename T, typename Y>
505 return lhs.get() != rhs.get();
506}
507
508template<typename T, typename Y>
509bool operator<(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NO_EXCEPT {
510 return lhs.get() < rhs.get();
511}
512
513template<typename T, typename Y>
515 return lhs.get() <= rhs.get();
516}
517
518template<typename T, typename Y>
519bool operator>(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NO_EXCEPT {
520 return lhs.get() > rhs.get();
521}
522
523template<typename T, typename Y>
525 return lhs.get() >= rhs.get();
526}
527
528template<typename T>
530 return lhs.get() == nullptr;
531}
532
533template<typename T>
535 return nullptr == rhs.get();
536}
537
538template<typename T>
540 return lhs.get() != nullptr;
541}
542
543template<typename T>
545 return nullptr != rhs.get();
546}
547
548// Utility functions
549template<typename T>
551 lhs.swap(rhs);
552}
553
554// Casts - using aliasing constructor (matches std::shared_ptr behavior)
555template<typename T, typename Y>
557 return shared_ptr<T>(other, static_cast<T*>(other.get()));
558}
559
560template<typename T, typename Y>
562 return shared_ptr<T>(other, const_cast<T*>(other.get()));
563}
564
565template<typename T, typename Y>
569
570} // namespace fl
571
572// Smart pointer typedef macros
573// These create convenient typedefs like FooPtr = fl::shared_ptr<Foo>
574
575// Forward declares a class and creates a shared_ptr typedef
576// Example: FASTLED_SHARED_PTR(Foo) -> creates FooPtr as fl::shared_ptr<Foo>
577#define FASTLED_SHARED_PTR(type) \
578 class type; \
579 using type##Ptr = fl::shared_ptr<type>;
580
581// Same as FASTLED_SHARED_PTR but for structs
582#define FASTLED_SHARED_PTR_STRUCT(type) \
583 struct type; \
584 using type##Ptr = fl::shared_ptr<type>;
585
586// Creates typedef without forward declaration (for template instantiations)
587// Example: using FooInt = Foo<int>; FASTLED_SHARED_PTR_NO_FWD(FooInt)
588#define FASTLED_SHARED_PTR_NO_FWD(type) using type##Ptr = fl::shared_ptr<type>;
589
590// Backward compatibility aliases (deprecated - prefer FASTLED_SHARED_PTR variants)
591#define FASTLED_SMART_PTR(type) FASTLED_SHARED_PTR(type)
592#define FASTLED_SMART_PTR_STRUCT(type) FASTLED_SHARED_PTR_STRUCT(type)
593#define FASTLED_SMART_PTR_NO_FWD(type) FASTLED_SHARED_PTR_NO_FWD(type)
Keeps fl's generic templates out of argument-dependent lookup (ADL).
Alignment macros and utilities for FastLED.
void reset(shared_ptr &&other) FL_NO_EXCEPT
Definition shared_ptr.h:312
bool operator!=(fl::nullptr_t) const FL_NO_EXCEPT
Definition shared_ptr.h:373
detail::ControlBlockBase * mControlBlock
Definition shared_ptr.h:166
shared_ptr() FL_NO_EXCEPT
Definition shared_ptr.h:202
shared_ptr(Y *ptr, Deleter d) FL_NO_EXCEPT
Definition shared_ptr.h:391
void swap(shared_ptr &other) FL_NO_EXCEPT
Definition shared_ptr.h:317
void swap(shared_ptr &&other) FL_NO_EXCEPT
Definition shared_ptr.h:322
T * get() const FL_NO_EXCEPT
Definition shared_ptr.h:342
friend shared_ptr< Y > make_shared_array(size_t n) FL_NO_EXCEPT
Definition shared_ptr.h:474
shared_ptr(Y *ptr) FL_NO_EXCEPT
Definition shared_ptr.h:381
long use_count() const FL_NO_EXCEPT
Definition shared_ptr.h:350
T * operator->() const FL_NO_EXCEPT
Definition shared_ptr.h:345
bool unique() const FL_NO_EXCEPT
Definition shared_ptr.h:358
bool operator==(fl::nullptr_t) const FL_NO_EXCEPT
Definition shared_ptr.h:369
friend shared_ptr< Y > make_shared_with_deleter(Deleter d, Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:449
shared_ptr(T *ptr, detail::ControlBlockBase *control_block, detail::no_tracking_tag) FL_NO_EXCEPT
Definition shared_ptr.h:175
shared_ptr(const weak_ptr< Y > &weak) FL_NO_EXCEPT
Definition weak_ptr.h:209
shared_ptr(shared_ptr &&other) FL_NO_EXCEPT
Definition shared_ptr.h:219
T & operator[](ptrdiff_t idx) const FL_NO_EXCEPT
Definition shared_ptr.h:347
shared_ptr(const shared_ptr< Y > &other, T *ptr) FL_NO_EXCEPT
Definition shared_ptr.h:239
shared_ptr(shared_ptr< Y > &&other) FL_NO_EXCEPT
Definition shared_ptr.h:226
shared_ptr(T *ptr, detail::ControlBlockBase *control_block, detail::make_shared_tag) FL_NO_EXCEPT
Definition shared_ptr.h:169
shared_ptr(fl::nullptr_t) FL_NO_EXCEPT
Definition shared_ptr.h:203
~shared_ptr() FL_DTOR_NOEXCEPT
Definition shared_ptr.h:245
bool is_no_tracking() const FL_NO_EXCEPT
Definition shared_ptr.h:363
shared_ptr & operator=(shared_ptr< Y > &&other) FL_NO_EXCEPT
Definition shared_ptr.h:282
shared_ptr & operator=(shared_ptr &&other) FL_NO_EXCEPT
Definition shared_ptr.h:272
shared_ptr & operator=(const shared_ptr &other) FL_NO_EXCEPT
Definition shared_ptr.h:252
friend class shared_ptr
Definition shared_ptr.h:399
shared_ptr(const shared_ptr &other) FL_NO_EXCEPT
Definition shared_ptr.h:208
void acquire() FL_NO_EXCEPT
Definition shared_ptr.h:191
shared_ptr & operator=(const shared_ptr< Y > &other) FL_NO_EXCEPT
Definition shared_ptr.h:264
shared_ptr(const shared_ptr< Y > &other) FL_NO_EXCEPT
Definition shared_ptr.h:214
friend shared_ptr< Y > make_shared_no_tracking(Y &obj) FL_NO_EXCEPT
T & operator*() const FL_NO_EXCEPT
Definition shared_ptr.h:344
shared_ptr< T > allocate_shared(const A &alloc, Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:490
shared_ptr< T > make_shared(Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:423
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_info.h:57
constexpr T && forward(typename remove_reference< T >::type &t) FL_NO_EXCEPT
Definition s16x16x4.h:236
decltype(nullptr) nullptr_t
Definition s16x16x4.h:13
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
void swap(array< T, N > &lhs, array< T, N > &rhs) FL_NO_EXCEPT
Definition array.h:209
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
constexpr int type_rank< T >::value
shared_ptr< T > const_pointer_cast(const shared_ptr< Y > &other) FL_NO_EXCEPT
Definition shared_ptr.h:561
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if two CRGB objects have the same color data.
Definition crgb.h:740
atomic< fl::u32 > atomic_u32
Definition atomic.h:32
FASTLED_FORCE_INLINE bool operator>(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if the sum of the color channels in one CRGB object is greater than another.
Definition crgb.h:761
shared_ptr< T > make_shared_array(size_t n) FL_NO_EXCEPT
Definition shared_ptr.h:474
FASTLED_FORCE_INLINE bool operator<=(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if the sum of the color channels in one CRGB object is less than or equal to another.
Definition crgb.h:779
struct FL_ALIGNAS(4) Wave3BitExpansionLut
Lookup table for nibble-to-waveform expansion in wave3 format (32 bytes)
Definition wave3.h:32
To bit_cast(const From &from) FL_NO_EXCEPT
Definition bit_cast.h:48
void aligned_free(void *ptr) FL_NO_EXCEPT
shared_ptr< T > make_shared_no_tracking(T &obj) FL_NO_EXCEPT
Definition shared_ptr.h:468
fl::ptrdiff ptrdiff_t
Definition s16x16x4.h:226
shared_ptr< T > static_pointer_cast(const shared_ptr< Y > &other) FL_NO_EXCEPT
Definition shared_ptr.h:556
FASTLED_FORCE_INLINE void * aligned_alloc(fl::size_t alignment, fl::size_t size) FL_NO_EXCEPT
Definition cstdlib.h:45
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if two CRGB objects do not have the same color data.
Definition crgb.h:746
shared_ptr< T > reinterpret_pointer_cast(const shared_ptr< Y > &other) FL_NO_EXCEPT
Definition shared_ptr.h:566
FASTLED_FORCE_INLINE bool operator>=(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if the sum of the color channels in one CRGB object is greater than or equal to another.
Definition crgb.h:770
shared_ptr< T > make_shared_with_deleter(Deleter d, Args &&... args) FL_NO_EXCEPT
Definition shared_ptr.h:449
FASTLED_FORCE_INLINE bool operator<(const CRGB &lhs, const CRGB &rhs) FL_NO_EXCEPT
Check if the sum of the color channels in one CRGB object is less than another.
Definition crgb.h:752
Base definition for an LED controller.
corkscrew_args args
Definition old.h:149
#define FL_DTOR_NOEXCEPT
#define FL_NO_EXCEPT
#define FL_ALIGNAS(N)
void destroy_object() FL_NO_EXCEPT override
Definition shared_ptr.h:95
void destroy_control_block() FL_NO_EXCEPT override
Definition shared_ptr.h:102
ControlBlock(T *p, Deleter d=Deleter(), bool track=true) FL_NO_EXCEPT
Definition shared_ptr.h:92
static constexpr fl::u32 NO_TRACKING_VALUE
Definition shared_ptr.h:41
virtual void destroy_control_block() FL_NO_EXCEPT=0
fl::atomic_u32 shared_count
Definition shared_ptr.h:37
void add_shared_ref() FL_NO_EXCEPT
virtual void destroy_object() FL_NO_EXCEPT=0
ControlBlockBase(bool track=true) FL_NO_EXCEPT
Definition shared_ptr.h:43
bool is_no_tracking() const FL_NO_EXCEPT
bool remove_shared_ref() FL_NO_EXCEPT
virtual ~ControlBlockBase() FL_DTOR_NOEXCEPT
void operator()(T *ptr) const FL_NO_EXCEPT
Definition shared_ptr.h:81
static constexpr fl::size value
Definition shared_ptr.h:111
void operator()(T *ptr) const FL_NO_EXCEPT
Definition shared_ptr.h:65
void operator()(T *) const FL_NO_EXCEPT
Definition shared_ptr.h:73