FastLED 3.9.15
Loading...
Searching...
No Matches
weak_ptr.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/shared_ptr.h"
4#include "fl/type_traits.h"
5
6namespace fl {
7
8// std::weak_ptr compatible implementation
9template<typename T>
10class weak_ptr {
11private:
12 T* ptr_;
14
15public:
16 using element_type = T;
17
18 // Default constructor
19 weak_ptr() noexcept : ptr_(nullptr), control_block_(nullptr) {}
20
21 // Copy constructor
22 weak_ptr(const weak_ptr& other) noexcept : ptr_(other.ptr_), control_block_(other.control_block_) {
23 if (control_block_) {
24 ++control_block_->weak_count;
25 }
26 }
27
28 // Converting copy constructor
29 template<typename Y>
30 weak_ptr(const weak_ptr<Y>& other) noexcept : ptr_(other.ptr_), control_block_(other.control_block_) {
31 if (control_block_) {
32 ++control_block_->weak_count;
33 }
34 }
35
36 // Constructor from shared_ptr
37 template<typename Y>
38 weak_ptr(const shared_ptr<Y>& shared) noexcept : ptr_(shared.ptr_), control_block_(shared.control_block_) {
39 if (control_block_) {
40 ++control_block_->weak_count;
41 }
42 }
43
44 // Move constructor
45 weak_ptr(weak_ptr&& other) noexcept : ptr_(other.ptr_), control_block_(other.control_block_) {
46 other.ptr_ = nullptr;
47 other.control_block_ = nullptr;
48 }
49
50 // Converting move constructor
51 template<typename Y>
52 weak_ptr(weak_ptr<Y>&& other) noexcept : ptr_(other.ptr_), control_block_(other.control_block_) {
53 other.ptr_ = nullptr;
54 other.control_block_ = nullptr;
55 }
56
57 // Destructor
59 release();
60 }
61
62 // Assignment operators
63 weak_ptr& operator=(const weak_ptr& other) noexcept {
64 if (this != &other) {
65 release();
66 ptr_ = other.ptr_;
67 control_block_ = other.control_block_;
68 if (control_block_) {
69 ++control_block_->weak_count;
70 }
71 }
72 return *this;
73 }
74
75 template<typename Y>
76 weak_ptr& operator=(const weak_ptr<Y>& other) noexcept {
77 release();
78 ptr_ = other.ptr_;
79 control_block_ = other.control_block_;
80 if (control_block_) {
81 ++control_block_->weak_count;
82 }
83 return *this;
84 }
85
86 template<typename Y>
87 weak_ptr& operator=(const shared_ptr<Y>& shared) noexcept {
88 release();
89 ptr_ = shared.ptr_;
90 control_block_ = shared.control_block_;
91 if (control_block_) {
92 ++control_block_->weak_count;
93 }
94 return *this;
95 }
96
97 weak_ptr& operator=(weak_ptr&& other) noexcept {
98 if (this != &other) {
99 release();
100 ptr_ = other.ptr_;
101 control_block_ = other.control_block_;
102 other.ptr_ = nullptr;
103 other.control_block_ = nullptr;
104 }
105 return *this;
106 }
107
108 template<typename Y>
109 weak_ptr& operator=(weak_ptr<Y>&& other) noexcept {
110 release();
111 ptr_ = other.ptr_;
112 control_block_ = other.control_block_;
113 other.ptr_ = nullptr;
114 other.control_block_ = nullptr;
115 return *this;
116 }
117
118 // Modifiers
119 void reset() noexcept {
120 release();
121 ptr_ = nullptr;
122 control_block_ = nullptr;
123 }
124
125 void swap(weak_ptr& other) noexcept {
126 fl::swap(ptr_, other.ptr_);
127 fl::swap(control_block_, other.control_block_);
128 }
129
130 // Observers
131 long use_count() const noexcept {
132 return control_block_ ? static_cast<long>(control_block_->shared_count) : 0;
133 }
134
135 bool expired() const noexcept {
136 return use_count() == 0;
137 }
138
139 shared_ptr<T> lock() const noexcept {
140 if (expired()) {
141 return shared_ptr<T>();
142 }
143
144 // Try to acquire the shared pointer atomically
145 if (control_block_ && control_block_->shared_count > 0) {
146 ++control_block_->shared_count;
148 }
149 return shared_ptr<T>();
150 }
151
152 // Ownership (similar to shared_ptr interface)
153 template<typename Y>
154 bool owner_before(const weak_ptr<Y>& other) const noexcept {
155 return control_block_ < other.control_block_;
156 }
157
158 template<typename Y>
159 bool owner_before(const shared_ptr<Y>& other) const noexcept {
160 return control_block_ < other.control_block_;
161 }
162
163 // Comparison operators (for compatibility with VectorSet)
164 bool operator==(const weak_ptr& other) const noexcept {
165 return ptr_ == other.ptr_ && control_block_ == other.control_block_;
166 }
167
168 bool operator!=(const weak_ptr& other) const noexcept {
169 return !(*this == other);
170 }
171
172 template<typename Y>
173 bool operator==(const weak_ptr<Y>& other) const noexcept {
174 return ptr_ == other.ptr_ && control_block_ == other.control_block_;
175 }
177 template<typename Y>
178 bool operator!=(const weak_ptr<Y>& other) const noexcept {
179 return !(*this == other);
180 }
181
182private:
183 void release() {
184 if (control_block_) {
185 if (--control_block_->weak_count == 0 && control_block_->shared_count == 0) {
186 control_block_->destroy_control_block();
187 }
188 }
189 }
190
191 template<typename Y> friend class weak_ptr;
192 template<typename Y> friend class shared_ptr;
193};
194
195// Utility functions
196template<typename T>
197void swap(weak_ptr<T>& lhs, weak_ptr<T>& rhs) noexcept {
198 lhs.swap(rhs);
199}
200
201} // namespace fl
202
203// Now we can complete the shared_ptr constructor that depends on weak_ptr
204namespace fl {
205
206template<typename T>
207template<typename Y>
208shared_ptr<T>::shared_ptr(const weak_ptr<Y>& weak) : ptr_(nullptr), control_block_(nullptr) {
209 if (!weak.expired()) {
210 if (weak.control_block_ && weak.control_block_->shared_count > 0) {
211 ++weak.control_block_->shared_count;
212 ptr_ = weak.ptr_;
213 control_block_ = weak.control_block_;
214 }
215 }
216 if (!ptr_) {
217 // If construction failed (object was destroyed), throw bad_weak_ptr equivalent
218 // For now, just leave as default-constructed (nullptr)
219 }
220}
221
222} // namespace fl
friend class weak_ptr
Definition shared_ptr.h:329
detail::ControlBlockBase * control_block_
Definition shared_ptr.h:109
friend class shared_ptr
Definition shared_ptr.h:328
detail::ControlBlockBase * control_block_
Definition weak_ptr.h:13
bool operator!=(const weak_ptr &other) const noexcept
Definition weak_ptr.h:168
weak_ptr(weak_ptr< Y > &&other) noexcept
Definition weak_ptr.h:52
friend class weak_ptr
Definition weak_ptr.h:191
weak_ptr() noexcept
Definition weak_ptr.h:19
bool operator==(const weak_ptr< Y > &other) const noexcept
Definition weak_ptr.h:173
bool owner_before(const shared_ptr< Y > &other) const noexcept
Definition weak_ptr.h:159
weak_ptr & operator=(weak_ptr &&other) noexcept
Definition weak_ptr.h:97
weak_ptr & operator=(const shared_ptr< Y > &shared) noexcept
Definition weak_ptr.h:87
weak_ptr & operator=(weak_ptr< Y > &&other) noexcept
Definition weak_ptr.h:109
void release()
Definition weak_ptr.h:183
bool operator!=(const weak_ptr< Y > &other) const noexcept
Definition weak_ptr.h:178
weak_ptr & operator=(const weak_ptr< Y > &other) noexcept
Definition weak_ptr.h:76
weak_ptr(const weak_ptr &other) noexcept
Definition weak_ptr.h:22
weak_ptr(const weak_ptr< Y > &other) noexcept
Definition weak_ptr.h:30
shared_ptr< T > lock() const noexcept
Definition weak_ptr.h:139
bool operator==(const weak_ptr &other) const noexcept
Definition weak_ptr.h:164
weak_ptr & operator=(const weak_ptr &other) noexcept
Definition weak_ptr.h:63
friend class shared_ptr
Definition weak_ptr.h:192
long use_count() const noexcept
Definition weak_ptr.h:131
void reset() noexcept
Definition weak_ptr.h:119
void swap(weak_ptr &other) noexcept
Definition weak_ptr.h:125
weak_ptr(weak_ptr &&other) noexcept
Definition weak_ptr.h:45
bool expired() const noexcept
Definition weak_ptr.h:135
bool owner_before(const weak_ptr< Y > &other) const noexcept
Definition weak_ptr.h:154
weak_ptr(const shared_ptr< Y > &shared) noexcept
Definition weak_ptr.h:38
void swap(array< T, N > &lhs, array< T, N > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition array.h:156
IMPORTANT!
Definition crgb.h:20