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