FastLED 3.9.15
Loading...
Searching...
No Matches
ptr.h
Go to the documentation of this file.
1// allow-include-after-namespace
2#pragma once
3
4// FastLED smart pointer.
5//
6// * Make your subclasses inherit from fl::Referent.
7// * `class Foo: public fl::Referent {};`
8// * Use a macro to declare your smart pointer.
9// * For regular, non-template classes:
10// * `FASTLED_SMART_PTR(Foo)` -> `FooPtr` is now available.
11// * For templates use `FASTLED_SMART_PTR_NO_FWD(Foo)`
12// * `template <typename T> class Foo {}; using FooInt = Foo<int>;`
13// * `FASTLED_SAMRT_PTR_NO_FWD(FooInt)`
14// * `FooIntPtr` is now available.
15// * Instantiate from heap
16// * `FooPtr foo = fl::make_intrusive<Foo>(a, b, ...args);`
17// * Use `foo->method()` to call methods.
18// * Instantiate from stack object and disable tracking
19// * `Foo foo; FooPtr fooPtr = FooPtr::NoTracking(foo);`
21
22#include "fl/namespace.h"
23#include "fl/scoped_ptr.h"
24#include "fl/type_traits.h"
25#include "fl/referent.h"
26#include "fl/bit_cast.h"
27#include "fl/int.h"
28#include "fl/deprecated.h"
29
30// Declares a smart pointer. FASTLED_SMART_PTR(Foo) will declare a class FooPtr
31// which will be a typedef of shared_ptr<Foo>. After this fl::make_intrusive<Foo>(...args) can be
32// used to create a new instance of shared_ptr<Foo>.
33#define FASTLED_SMART_PTR(type) \
34 class type; \
35 using type##Ptr = fl::shared_ptr<type>;
36
37#define FASTLED_SMART_PTR_STRUCT(type) \
38 struct type; \
39 using type##Ptr = fl::shared_ptr<type>;
40
41#define FASTLED_SMART_PTR_NO_FWD(type) using type##Ptr = fl::shared_ptr<type>;
42
43// If you have an interface class that you want to create a smart pointer for,
44// then you need to use this to bind it to a constructor.
45#define FASTLED_SMART_PTR_CONSTRUCTOR(type, constructor) \
46 template <> class PtrTraits<type> { \
47 public: \
48 template <typename... Args> static shared_ptr<type> New(Args... args) { \
49 fl::shared_ptr<type> ptr = constructor(args...); \
50 return ptr; \
51 } \
52 };
53
54namespace fl {
55
56class Referent; // Inherit this if you want your object to be able to go into a
57 // Ptr, or WeakPtr.
58template <typename T> class Ptr; // Reference counted smart pointer base class.
59template <typename T> class WeakPtr; // Weak reference smart pointer base class.
60
61template <typename T, typename... Args> Ptr<T> NewPtr(Args... args);
62
63template <typename T, typename... Args> Ptr<T> NewPtrNoTracking(Args... args);
64
65template <typename T> class PtrTraits {
66 public:
67 using element_type = T;
69
70 template <typename... Args> static Ptr<T> New(Args... args);
71 static Ptr<T> New();
72};
73
74// Ptr is a reference-counted smart pointer that manages the lifetime of an
75// object.
76//
77// It will work with any class implementing ref(), unref() and destroy().
78//
79// Please note that this Ptr class is "sticky" to it's referent, that is, no
80// automatic conversion from raw pointers to Ptr or vice versa is allowed and
81// must be done explicitly, see the Ptr::TakeOwnership() and Ptr::NoTracking()
82// methods.
83//
84// To create a Ptr to a concrete object, it's best to use FASTLED_SMART_PTR(Foo)
85// and then use fl::make_intrusive<Foo>(...) to create a new instance of Ptr<Foo>.
86//
87// To create a Ptr of an interface bound to a subclass (common for driver code
88// or when hiding implementation) use the Ptr<InterfaceClass>::TakeOwnership(new
89// Subclass()) method.
90//
91// For objects created statically, use Ptr<Referent>::NoTracking(referent) to
92// create a Ptr, as this will disable reference tracking but still allow it to
93// be used as a Ptr.
94//
95// Example:
96// FASTLED_SMART_PTR(Foo);
97// class Foo: public fl::Referent {};
98// FooPtr foo = fl::make_intrusive<Foo>();
99//
100// Example 2: (Manual binding to constructor)
101// class FooSubclass: public Foo {};
102// Ptr<Foo> bar = Ptr<FooSubclass>::TakeOwnership(new FooSubclass());
103//
104// Example 3: (Provide your own constructor so that fl::make_intrusive<Foo>() works to
105// create a FooSubclass)
106// class FooSubclass: public Foo { // Foo is an interface, FooSubclass is an
107// implementation.
108// public:
109// static FooPtr New(int a, int b);
110// };
111// FASTLED_SMART_PTR_CONSTRUCTOR(Foo, FooSubclass::New);
112// FooPtr foo = fl::make_intrusive<Foo>(1, 2); // this will now work.
113// NOTE: This is legacy - new code should use fl::shared_ptr<T> instead
114template <typename T> class Ptr : public PtrTraits<T> {
115 public:
116 friend class PtrTraits<T>;
117
118 template <typename... Args>
119 static Ptr<T> New(Args... args);
120
121 // Used for low level allocations, typically for pointer to an
122 // implementation where it needs to convert to a Ptr of a base class.
123 // NOTE: Legacy method - use fl::shared_ptr<T> constructor or fl::make_shared<T>() instead
124 static Ptr TakeOwnership(T *ptr) { return Ptr(ptr, true); }
125
126 // Used for low level allocations, typically to handle memory that is
127 // statically allocated where the destructor should not be called when
128 // the refcount reaches 0.
129 // NOTE: Legacy method - use fl::make_shared_no_tracking<T>() instead
130 static Ptr NoTracking(T &referent) { return Ptr(&referent, false); }
131
132 static Ptr Null() { return Ptr<T>(); }
133
134 // Allow upcasting of Refs.
135 template <typename U, typename = fl::is_derived<T, U>>
136 // NOTE: Legacy constructor - use fl::shared_ptr<T> instead of fl::Ptr<T>
137 Ptr(const Ptr<U> &refptr);
138
139 // NOTE: Legacy constructor - use fl::shared_ptr<T> instead of fl::Ptr<T>
140 Ptr() : referent_(nullptr) {}
141
142 // Forbidden to convert a raw pointer to a Referent into a Ptr, because
143 // it's possible that the raw pointer comes from the stack or static memory.
144 Ptr(T *referent) = delete;
145 Ptr &operator=(T *referent) = delete;
146
147 // NOTE: Legacy constructor - use fl::shared_ptr<T> instead of fl::Ptr<T>
148 Ptr(const Ptr &other);
149 // NOTE: Legacy constructor - use fl::shared_ptr<T> instead of fl::Ptr<T>
150 Ptr(Ptr &&other) noexcept;
151 ~Ptr();
152
153 // NOTE: Legacy assignment - use fl::shared_ptr<T> instead of fl::Ptr<T>
154 Ptr &operator=(const Ptr &other);
155 // NOTE: Legacy assignment - use fl::shared_ptr<T> instead of fl::Ptr<T>
156 Ptr &operator=(Ptr &&other) noexcept;
157
158 // Either returns the weakptr if it exists, or an empty weakptr.
160 WeakPtr<T> weakPtr() const { return WeakPtr<T>(*this); }
161
162 bool operator==(const T *other) const { return referent_ == other; }
163 bool operator!=(const T *other) const { return referent_ != other; }
164 bool operator==(const Ptr &other) const { return referent_ == other.referent_; }
165 bool operator!=(const Ptr &other) const { return referent_ != other.referent_; }
166 bool operator<(const Ptr &other) const { return referent_ < other.referent_; }
167
168 T *get() const { return referent_; }
169 T *operator->() const { return referent_; }
170 T &operator*() const { return *referent_; }
171 explicit operator bool() const noexcept { return referent_ != nullptr; }
172
173 void reset();
174 void reset(Ptr<T> &refptr);
175
176 // Releases the pointer from reference counting from this Ptr.
177 T *release();
178
179 void swap(Ptr &other) noexcept;
180 bool isOwned() const { return referent_ && referent_->ref_count() > 0; }
181
182 private:
183 Ptr(T *referent, bool from_heap);
185};
186
187// NOTE: This is legacy - new code should use fl::weak_ptr<T> instead
188template <typename T> class WeakPtr {
189 public:
190 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
191 WeakPtr() : mWeakPtr(nullptr) {}
192
193 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
194 WeakPtr(const Ptr<T> &ptr);
195
196 template <typename U>
197 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
198 WeakPtr(const Ptr<U> &ptr);
199
200 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
201 WeakPtr(const WeakPtr &other);
202
203 template <typename U>
204 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
205 WeakPtr(const WeakPtr<U> &other);
206
207 // NOTE: Legacy constructor - use fl::weak_ptr<T> instead of fl::WeakPtr<T>
208 WeakPtr(WeakPtr &&other) noexcept;
209
210 ~WeakPtr();
211
212 operator bool() const;
213 bool operator!() const;
214 bool operator==(const WeakPtr &other) const;
215 bool operator!=(const WeakPtr &other) const;
216 bool operator==(const T *other) const;
217 bool operator==(T *other) const;
218 bool operator==(const Ptr<T> &other) const;
219 bool operator!=(const T *other) const;
220
221 WeakPtr &operator=(const WeakPtr &other);
222
223 Ptr<T> lock() const;
224
225 bool expired() const;
226
227 void reset();
228
229 fl::uptr ptr_value() const {
230 fl::uptr val = fl::bit_cast<fl::uptr>(mWeakPtr);
231 return val;
232 }
233
235};
236
237template <typename T, typename... Args>
238// NOTE: Legacy function - use fl::make_shared<T>(...) instead of fl::NewPtr<T>(...)
239Ptr<T> NewPtr(Args... args);
240
241template <typename T>
242// NOTE: Legacy function - use fl::make_shared_no_tracking<T>() instead of fl::NewPtrNoTracking<T>()
244
245} // namespace fl
246
247// Template implementations must always be available for instantiation
248// This achieves the goal of separating declarations from implementations
249// while ensuring templates work correctly in all compilation modes
250#include "fl/ptr_impl.h"
void reset()
Definition ptr_impl.h:84
Ptr()
Definition ptr.h:140
bool operator<(const Ptr &other) const
Definition ptr.h:166
T * referent_
Definition ptr.h:184
Ptr(T *referent)=delete
static Ptr TakeOwnership(T *ptr)
Definition ptr.h:124
void swap(Ptr &other) noexcept
Definition ptr_impl.h:112
WeakPtr< T > weakRefNoCreate() const
Definition ptr_impl.h:287
Ptr(const Ptr< U > &refptr)
Definition ptr_impl.h:32
bool operator==(const Ptr &other) const
Definition ptr.h:164
static Ptr NoTracking(T &referent)
Definition ptr.h:130
bool operator!=(const Ptr &other) const
Definition ptr.h:165
T * release()
Definition ptr_impl.h:105
static Ptr Null()
Definition ptr.h:132
Ptr & operator=(T *referent)=delete
T * get() const
Definition ptr.h:168
bool isOwned() const
Definition ptr.h:180
WeakPtr< T > weakPtr() const
Definition ptr.h:160
bool operator==(const T *other) const
Definition ptr.h:162
bool operator!=(const T *other) const
Definition ptr.h:163
T & operator*() const
Definition ptr.h:170
T * operator->() const
Definition ptr.h:169
Definition ptr.h:114
T element_type
Definition ptr.h:67
Ptr< T > ptr_type
Definition ptr.h:68
static Ptr< T > New()
Definition ptr_impl.h:18
WeakPtr & operator=(const WeakPtr &other)
Definition ptr_impl.h:188
fl::uptr ptr_value() const
Definition ptr.h:229
bool expired() const
Definition ptr_impl.h:220
bool operator!() const
Definition ptr_impl.h:236
bool operator==(const WeakPtr &other) const
Definition ptr_impl.h:242
bool operator!=(const WeakPtr &other) const
Definition ptr_impl.h:247
void reset()
Definition ptr_impl.h:279
WeakPtr()
Definition ptr.h:191
Ptr< T > lock() const
Definition ptr_impl.h:202
WeakReferent * mWeakPtr
Definition ptr.h:234
Implements the FastLED namespace macros.
To bit_cast(const From &from) noexcept
Definition bit_cast.h:39
Ptr< T > NewPtr(Args... args)
Definition ptr_impl.h:313
Ptr< T > NewPtrNoTracking(Args... args)
IMPORTANT!
Definition crgb.h:20
corkscrew_args args
Definition old.h:150