FastLED 3.9.15
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_NOEXCEPT
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_NOEXCEPT = 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_NOEXCEPT;
52};
53
54// Default deleter implementation
55template<typename T>
57 void operator()(T* ptr) const FL_NOEXCEPT {
58 delete ptr;
59 }
60};
61
62// Deleter that does nothing (for stack/static objects)
63template<typename T>
65 void operator()(T*) const FL_NOEXCEPT {
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_NOEXCEPT {
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_NOEXCEPT
85 : ControlBlockBase(track), ptr(p), deleter(d) {}
86
87 void destroy_object() FL_NOEXCEPT 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_NOEXCEPT
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_NOEXCEPT {
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_NOEXCEPT {
131 return fl::bit_cast<T*>(&storage[0]);
132 }
133
134 const T* get_object() const FL_NOEXCEPT {
135 return fl::bit_cast<const T*>(&storage[0]);
136 }
137
138 void destroy_object() FL_NOEXCEPT 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_NOEXCEPT 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_NOEXCEPT : mPtr(nullptr), mControlBlock(nullptr) {}
196
197
198
199 // Copy constructor
200 shared_ptr(const shared_ptr& other) FL_NOEXCEPT : 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_NOEXCEPT : mPtr(static_cast<T*>(other.mPtr)), mControlBlock(other.mControlBlock) {
207 acquire();
208 }
209
210 // Move constructor
211 shared_ptr(shared_ptr&& other) FL_NOEXCEPT : 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_NOEXCEPT : 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_NOEXCEPT;
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_NOEXCEPT { return mPtr; }
335
336 T& operator*() const FL_NOEXCEPT { return *mPtr; }
337 T* operator->() const FL_NOEXCEPT { return mPtr; }
338
339 T& operator[](ptrdiff_t idx) const FL_NOEXCEPT { return mPtr[idx]; }
340
341 // NEW: use_count returns 0 for no-tracking shared_ptrs
342 long use_count() const FL_NOEXCEPT {
343 if (!mControlBlock) return 0;
345 return 0;
346 }
347 return static_cast<long>(mControlBlock->shared_count);
348 }
349
350 bool unique() const FL_NOEXCEPT { return use_count() == 1; }
351
352 explicit operator bool() const FL_NOEXCEPT { 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_NOEXCEPT : 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_NOEXCEPT : 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_NOEXCEPT;
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 auto* control = new detail::InlinedControlBlock<T>();
416 T* obj = control->get_object();
417 new(obj) T(fl::forward<Args>(args)...); // Placement new
418 control->object_constructed = true;
419 return shared_ptr<T>(obj, control, detail::make_shared_tag{});
420}
421
422template<typename T, typename Deleter, typename... Args>
424 T* obj = new T(fl::forward<Args>(args)...);
425 auto* control = new detail::ControlBlock<T, Deleter>(obj, d);
426 //new(control->get_object()) T(fl::forward<Args>(args)...);
427 //control->object_constructed = true;
428 return shared_ptr<T>(obj, control, detail::make_shared_tag{});
429}
430
431// NEW: Creates a shared_ptr that does not modify the reference count
432// The shared_ptr and any copies will not affect object lifetime.
433// No control block is allocated - this is a zero-overhead wrapper around a raw pointer.
434template<typename T>
438
439// make_shared_array for array allocations
440template<typename T>
442 T* arr = new T[n](); // Zero-initialize the array
444 return shared_ptr<T>(arr, control, detail::make_shared_tag{});
445}
446
447// allocate_shared (simplified version without full allocator support for now)
448template<typename T, typename A, typename... Args>
449shared_ptr<T> allocate_shared(const A& /* alloc */, Args&&... args) FL_NOEXCEPT {
450 // For now, just delegate to make_shared
451 // Full allocator support would require more complex control block management
453}
454
455// Non-member comparison operators
456template<typename T, typename Y>
457bool operator==(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
458 return lhs.get() == rhs.get();
459}
460
461template<typename T, typename Y>
462bool operator!=(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
463 return lhs.get() != rhs.get();
464}
465
466template<typename T, typename Y>
467bool operator<(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
468 return lhs.get() < rhs.get();
469}
470
471template<typename T, typename Y>
472bool operator<=(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
473 return lhs.get() <= rhs.get();
474}
475
476template<typename T, typename Y>
477bool operator>(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
478 return lhs.get() > rhs.get();
479}
480
481template<typename T, typename Y>
482bool operator>=(const shared_ptr<T>& lhs, const shared_ptr<Y>& rhs) FL_NOEXCEPT {
483 return lhs.get() >= rhs.get();
484}
485
486template<typename T>
488 return lhs.get() == nullptr;
489}
490
491template<typename T>
493 return nullptr == rhs.get();
494}
495
496template<typename T>
498 return lhs.get() != nullptr;
499}
500
501template<typename T>
503 return nullptr != rhs.get();
504}
505
506// Utility functions
507template<typename T>
509 lhs.swap(rhs);
510}
511
512// Casts - using aliasing constructor (matches std::shared_ptr behavior)
513template<typename T, typename Y>
515 return shared_ptr<T>(other, static_cast<T*>(other.get()));
516}
517
518template<typename T, typename Y>
520 return shared_ptr<T>(other, const_cast<T*>(other.get()));
521}
522
523template<typename T, typename Y>
527
528} // namespace fl
529
530// Smart pointer typedef macros
531// These create convenient typedefs like FooPtr = fl::shared_ptr<Foo>
532
533// Forward declares a class and creates a shared_ptr typedef
534// Example: FASTLED_SHARED_PTR(Foo) -> creates FooPtr as fl::shared_ptr<Foo>
535#define FASTLED_SHARED_PTR(type) \
536 class type; \
537 using type##Ptr = fl::shared_ptr<type>;
538
539// Same as FASTLED_SHARED_PTR but for structs
540#define FASTLED_SHARED_PTR_STRUCT(type) \
541 struct type; \
542 using type##Ptr = fl::shared_ptr<type>;
543
544// Creates typedef without forward declaration (for template instantiations)
545// Example: using FooInt = Foo<int>; FASTLED_SHARED_PTR_NO_FWD(FooInt)
546#define FASTLED_SHARED_PTR_NO_FWD(type) using type##Ptr = fl::shared_ptr<type>;
547
548// Backward compatibility aliases (deprecated - prefer FASTLED_SHARED_PTR variants)
549#define FASTLED_SMART_PTR(type) FASTLED_SHARED_PTR(type)
550#define FASTLED_SMART_PTR_STRUCT(type) FASTLED_SHARED_PTR_STRUCT(type)
551#define FASTLED_SMART_PTR_NO_FWD(type) FASTLED_SHARED_PTR_NO_FWD(type)
Alignment macros and utilities for FastLED.
shared_ptr(fl::nullptr_t) FL_NOEXCEPT
Definition shared_ptr.h:195
detail::ControlBlockBase * mControlBlock
Definition shared_ptr.h:158
shared_ptr(T *ptr, detail::ControlBlockBase *control_block, detail::make_shared_tag) FL_NOEXCEPT
Definition shared_ptr.h:161
T & operator[](ptrdiff_t idx) const FL_NOEXCEPT
Definition shared_ptr.h:339
shared_ptr & operator=(shared_ptr &&other) FL_NOEXCEPT
Definition shared_ptr.h:264
shared_ptr(shared_ptr &&other) FL_NOEXCEPT
Definition shared_ptr.h:211
void swap(shared_ptr &&other) FL_NOEXCEPT
Definition shared_ptr.h:314
void acquire() FL_NOEXCEPT
Definition shared_ptr.h:183
void reset() FL_NOEXCEPT
Definition shared_ptr.h:286
weak_ptr< filebuf > weak_type
Definition shared_ptr.h:191
friend shared_ptr< Y > make_shared_array(size_t n) FL_NOEXCEPT
Definition shared_ptr.h:441
long use_count() const FL_NOEXCEPT
Definition shared_ptr.h:342
shared_ptr(shared_ptr< Y > &&other) FL_NOEXCEPT
Definition shared_ptr.h:218
shared_ptr & operator=(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:256
friend shared_ptr< Y > allocate_shared(const A &alloc, Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:449
shared_ptr(Y *ptr) FL_NOEXCEPT
Definition shared_ptr.h:373
friend shared_ptr< Y > make_shared_with_deleter(Deleter d, Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:423
bool operator!=(fl::nullptr_t) const FL_NOEXCEPT
Definition shared_ptr.h:365
friend shared_ptr< Y > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
shared_ptr & operator=(const shared_ptr &other) FL_NOEXCEPT
Definition shared_ptr.h:244
~shared_ptr() FL_NOEXCEPT
Definition shared_ptr.h:237
shared_ptr & operator=(shared_ptr< Y > &&other) FL_NOEXCEPT
Definition shared_ptr.h:274
friend shared_ptr< Y > make_shared_no_tracking(Y &obj) FL_NOEXCEPT
void reset(shared_ptr &&other) FL_NOEXCEPT
Definition shared_ptr.h:304
bool operator==(fl::nullptr_t) const FL_NOEXCEPT
Definition shared_ptr.h:361
shared_ptr(T *ptr, detail::ControlBlockBase *control_block, detail::no_tracking_tag) FL_NOEXCEPT
Definition shared_ptr.h:167
bool unique() const FL_NOEXCEPT
Definition shared_ptr.h:350
T * get() const FL_NOEXCEPT
Definition shared_ptr.h:334
friend class shared_ptr
Definition shared_ptr.h:391
shared_ptr(Y *ptr, Deleter d) FL_NOEXCEPT
Definition shared_ptr.h:383
T & operator*() const FL_NOEXCEPT
Definition shared_ptr.h:336
T * operator->() const FL_NOEXCEPT
Definition shared_ptr.h:337
bool is_no_tracking() const FL_NOEXCEPT
Definition shared_ptr.h:355
shared_ptr(const shared_ptr &other) FL_NOEXCEPT
Definition shared_ptr.h:200
shared_ptr(const weak_ptr< Y > &weak) FL_NOEXCEPT
Definition weak_ptr.h:209
void swap(shared_ptr &other) FL_NOEXCEPT
Definition shared_ptr.h:309
shared_ptr(const shared_ptr< Y > &other, T *ptr) FL_NOEXCEPT
Definition shared_ptr.h:231
shared_ptr(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:206
shared_ptr() FL_NOEXCEPT
Definition shared_ptr.h:194
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
constexpr T && forward(typename remove_reference< T >::type &t) FL_NOEXCEPT
Definition s16x16x4.h:234
decltype(nullptr) nullptr_t
Definition s16x16x4.h:13
__SIZE_TYPE__ size_t
Definition s16x16x4.h:16
shared_ptr< T > reinterpret_pointer_cast(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:524
constexpr int type_rank< T >::value
shared_ptr< T > const_pointer_cast(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:519
void aligned_free(void *ptr)
shared_ptr< T > make_shared_no_tracking(T &obj) FL_NOEXCEPT
Definition shared_ptr.h:435
void * aligned_alloc(fl::size_t alignment, fl::size_t size)
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects do not have the same color data.
Definition crgb.h:739
void swap(array< T, N > &lhs, array< T, N > &rhs) FL_NOEXCEPT
Definition array.h:209
atomic< fl::u32 > atomic_u32
Definition atomic.h:32
shared_ptr< T > make_shared_array(size_t n) FL_NOEXCEPT
Definition shared_ptr.h:441
FASTLED_FORCE_INLINE bool operator<(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than another.
Definition crgb.h:745
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if two CRGB objects have the same color data.
Definition crgb.h:733
shared_ptr< T > make_shared(Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:414
FASTLED_FORCE_INLINE bool operator>(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than another.
Definition crgb.h:754
struct FL_ALIGNAS(4) Wave3BitExpansionLut
Lookup table for nibble-to-waveform expansion in wave3 format (32 bytes)
Definition wave3.h:31
FASTLED_FORCE_INLINE bool operator<=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is less than or equal to another.
Definition crgb.h:772
shared_ptr< T > allocate_shared(const A &, Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:449
shared_ptr< T > static_pointer_cast(const shared_ptr< Y > &other) FL_NOEXCEPT
Definition shared_ptr.h:514
fl::ptrdiff ptrdiff_t
Definition s16x16x4.h:226
To bit_cast(const From &from) FL_NOEXCEPT
Definition bit_cast.h:48
shared_ptr< T > make_shared_with_deleter(Deleter d, Args &&... args) FL_NOEXCEPT
Definition shared_ptr.h:423
FASTLED_FORCE_INLINE bool operator>=(const CRGB &lhs, const CRGB &rhs) FL_NOEXCEPT
Check if the sum of the color channels in one CRGB object is greater than or equal to another.
Definition crgb.h:763
Base definition for an LED controller.
Definition crgb.hpp:179
corkscrew_args args
Definition old.h:149
#define FL_ALIGNAS(N)
#define FL_NOEXCEPT
ControlBlock(T *p, Deleter d=Deleter(), bool track=true) FL_NOEXCEPT
Definition shared_ptr.h:84
void destroy_object() FL_NOEXCEPT override
Definition shared_ptr.h:87
void destroy_control_block() FL_NOEXCEPT override
Definition shared_ptr.h:94
static constexpr fl::u32 NO_TRACKING_VALUE
Definition shared_ptr.h:33
virtual void destroy_control_block() FL_NOEXCEPT=0
fl::atomic_u32 shared_count
Definition shared_ptr.h:29
bool remove_shared_ref() FL_NOEXCEPT
virtual ~ControlBlockBase() FL_NOEXCEPT
ControlBlockBase(bool track=true) FL_NOEXCEPT
Definition shared_ptr.h:35
virtual void destroy_object() FL_NOEXCEPT=0
void add_shared_ref() FL_NOEXCEPT
bool is_no_tracking() const FL_NOEXCEPT
void operator()(T *ptr) const FL_NOEXCEPT
Definition shared_ptr.h:73
static constexpr fl::size value
Definition shared_ptr.h:103
void operator()(T *ptr) const FL_NOEXCEPT
Definition shared_ptr.h:57
void operator()(T *) const FL_NOEXCEPT
Definition shared_ptr.h:65