Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
weak_ptr.h
1// Copyright 2025 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include "pw_allocator/config.h"
17
18// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
19#if PW_ALLOCATOR_HAS_ATOMICS
20
21#include <cstddef>
22#include <utility>
23
24#include "pw_allocator/internal/control_block.h"
25#include "pw_allocator/internal/managed_ptr.h"
26#include "pw_allocator/shared_ptr.h"
27
28namespace pw {
29
34template <typename T>
35class WeakPtr final : public ::pw::allocator::internal::WeakManagedPtr<T> {
36 private:
37 using Base = ::pw::allocator::internal::WeakManagedPtr<T>;
38 using ControlBlock = ::pw::allocator::internal::ControlBlock;
39
40 public:
41 using element_type = typename Base::element_type;
42
44 constexpr WeakPtr() noexcept = default;
45
47 constexpr WeakPtr(std::nullptr_t) noexcept : WeakPtr() {}
48
50 WeakPtr(const WeakPtr& other) noexcept { *this = other; }
51
56 template <typename U>
57 WeakPtr(const WeakPtr<U>& other) noexcept {
58 *this = other;
59 }
60
65 template <typename U>
66 WeakPtr(const SharedPtr<U>& other) noexcept {
67 *this = other;
68 }
69
75 template <typename U>
76 WeakPtr(WeakPtr<U>&& other) noexcept {
77 *this = other;
78 }
79
80 ~WeakPtr() { reset(); }
81
83 constexpr WeakPtr& operator=(const WeakPtr& other) noexcept {
84 operator= <T>(other);
85 return *this;
86 }
87
92 template <typename U>
93 WeakPtr& operator=(const WeakPtr<U>& other) noexcept;
94
99 template <typename U>
100 WeakPtr& operator=(const SharedPtr<U>& other) noexcept;
101
106 template <typename U>
107 WeakPtr& operator=(WeakPtr<U>&& other) noexcept;
108
113 void reset() noexcept;
114
116 void swap(WeakPtr& other) noexcept {
117 std::swap(control_block_, other.control_block_);
118 }
119
122 int32_t use_count() const noexcept {
123 return control_block_ == nullptr ? 0 : control_block_->num_shared();
124 }
125
128 bool expired() const noexcept { return use_count() == 0; }
129
132 SharedPtr<T> Lock() const noexcept;
133
136 template <typename PtrType>
137 bool owner_before(const PtrType& other) const noexcept {
138 return control_block_ < other.control_block();
139 }
140
141 private:
142 // Allow WeakPtr<T> to access WeakPtr<U> and vice versa.
143 template <typename>
144 friend class WeakPtr;
145
146 ControlBlock* control_block() const { return control_block_; }
147
148 ControlBlock* control_block_ = nullptr;
149};
150
151// Template implementations.
152
153template <typename T>
154template <typename U>
155WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& other) noexcept {
156 Base::template CheckAssignable<U>();
157 control_block_ = other.control_block_;
158 if (control_block_ != nullptr) {
159 control_block_->IncrementWeak();
160 }
161 return *this;
162}
163
164template <typename T>
165template <typename U>
166WeakPtr<T>& WeakPtr<T>::operator=(const SharedPtr<U>& other) noexcept {
167 Base::template CheckAssignable<U>();
168 control_block_ = other.control_block_;
169 if (control_block_ != nullptr) {
170 control_block_->IncrementWeak();
171 }
172 return *this;
173}
174
175template <typename T>
176template <typename U>
177WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& other) noexcept {
178 Base::template CheckAssignable<U>();
179 control_block_ = other.control_block_;
180 other.control_block_ = nullptr;
181 return *this;
182}
183
184template <typename T>
185void WeakPtr<T>::reset() noexcept {
186 if (control_block_ == nullptr ||
187 control_block_->DecrementWeak() != ControlBlock::Action::kFree) {
188 return;
189 }
190 Allocator* allocator = control_block_->allocator();
191 Base::Deallocate(allocator, control_block_);
192 control_block_ = nullptr;
193}
194
195template <typename T>
197 if (control_block_ == nullptr || !control_block_->IncrementShared()) {
198 return SharedPtr<T>();
199 }
200 void* data = control_block_->data();
201 auto* t = std::launder(reinterpret_cast<element_type*>(data));
202 return SharedPtr<T>(t, control_block_);
203}
204
205} // namespace pw
206
207// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
208#endif // PW_ALLOCATOR_HAS_ATOMICS
Definition: allocator.h:34
Definition: shared_ptr.h:57
Definition: weak_ptr.h:35
void reset() noexcept
Definition: weak_ptr.h:185
WeakPtr(WeakPtr< U > &&other) noexcept
Definition: weak_ptr.h:76
WeakPtr(const WeakPtr &other) noexcept
Copy-constructs a WeakPtr<T> from a WeakPtr<T>.
Definition: weak_ptr.h:50
WeakPtr & operator=(const SharedPtr< U > &other) noexcept
int32_t use_count() const noexcept
Definition: weak_ptr.h:122
WeakPtr(const WeakPtr< U > &other) noexcept
Definition: weak_ptr.h:57
WeakPtr & operator=(const WeakPtr< U > &other) noexcept
constexpr WeakPtr & operator=(const WeakPtr &other) noexcept
Copy-assigns a WeakPtr<T> from a WeakPtr<T>.
Definition: weak_ptr.h:83
SharedPtr< T > Lock() const noexcept
Definition: weak_ptr.h:196
WeakPtr(const SharedPtr< U > &other) noexcept
Definition: weak_ptr.h:66
constexpr WeakPtr() noexcept=default
Creates an empty (nullptr) instance.
bool expired() const noexcept
Definition: weak_ptr.h:128
WeakPtr & operator=(WeakPtr< U > &&other) noexcept
void swap(WeakPtr &other) noexcept
Swaps the managed pointer and deallocator of this and another object.
Definition: weak_ptr.h:116
bool owner_before(const PtrType &other) const noexcept
Definition: weak_ptr.h:137
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27