C/C++ API Reference
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
31
36template <typename T>
37class WeakPtr final : public ::pw::allocator::internal::WeakManagedPtr<T> {
38 private:
39 using Base = ::pw::allocator::internal::WeakManagedPtr<T>;
40 using ControlBlock = ::pw::allocator::internal::ControlBlock;
41
42 public:
43 using element_type = typename Base::element_type;
44
46 constexpr WeakPtr() noexcept = default;
47
49 constexpr WeakPtr(std::nullptr_t) noexcept : WeakPtr() {}
50
52 WeakPtr(const WeakPtr& other) noexcept { *this = other; }
53
58 template <typename U>
59 WeakPtr(const WeakPtr<U>& other) noexcept {
60 *this = other;
61 }
62
67 template <typename U>
68 WeakPtr(const SharedPtr<U>& other) noexcept {
69 *this = other;
70 }
71
77 template <typename U>
78 WeakPtr(WeakPtr<U>&& other) noexcept {
79 *this = other;
80 }
81
82 ~WeakPtr() { reset(); }
83
85 constexpr WeakPtr& operator=(const WeakPtr& other) noexcept {
86 operator= <T>(other);
87 return *this;
88 }
89
94 template <typename U>
95 WeakPtr& operator=(const WeakPtr<U>& other) noexcept;
96
101 template <typename U>
102 WeakPtr& operator=(const SharedPtr<U>& other) noexcept;
103
108 template <typename U>
109 WeakPtr& operator=(WeakPtr<U>&& other) noexcept;
110
115 void reset() noexcept;
116
118 void swap(WeakPtr& other) noexcept {
119 std::swap(control_block_, other.control_block_);
120 }
121
124 int32_t use_count() const noexcept {
125 return control_block_ == nullptr ? 0 : control_block_->num_shared();
126 }
127
130 bool expired() const noexcept { return use_count() == 0; }
131
134 SharedPtr<T> Lock() const noexcept;
135
138 template <typename PtrType>
139 bool owner_before(const PtrType& other) const noexcept {
140 return control_block_ < other.control_block();
141 }
142
143 private:
144 // Allow WeakPtr<T> to access WeakPtr<U> and vice versa.
145 template <typename>
146 friend class WeakPtr;
147
148 ControlBlock* control_block() const { return control_block_; }
149
150 ControlBlock* control_block_ = nullptr;
151};
152
153// Template implementations.
154
155template <typename T>
156template <typename U>
157WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& other) noexcept {
158 Base::template CheckAssignable<U>();
159 control_block_ = other.control_block_;
160 if (control_block_ != nullptr) {
161 control_block_->IncrementWeak();
162 }
163 return *this;
164}
165
166template <typename T>
167template <typename U>
168WeakPtr<T>& WeakPtr<T>::operator=(const SharedPtr<U>& other) noexcept {
169 Base::template CheckAssignable<U>();
170 control_block_ = other.control_block_;
171 if (control_block_ != nullptr) {
172 control_block_->IncrementWeak();
173 }
174 return *this;
175}
176
177template <typename T>
178template <typename U>
179WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& other) noexcept {
180 Base::template CheckAssignable<U>();
181 control_block_ = other.control_block_;
182 other.control_block_ = nullptr;
183 return *this;
184}
185
186template <typename T>
187void WeakPtr<T>::reset() noexcept {
188 if (control_block_ == nullptr ||
189 control_block_->DecrementWeak() != ControlBlock::Action::kFree) {
190 return;
191 }
192 Allocator* allocator = control_block_->allocator();
193 Base::Deallocate(allocator, control_block_);
194 control_block_ = nullptr;
195}
196
197template <typename T>
199 if (control_block_ == nullptr || !control_block_->IncrementShared()) {
200 return SharedPtr<T>();
201 }
202 void* data = control_block_->data();
203 auto* t = std::launder(reinterpret_cast<element_type*>(data));
204 return SharedPtr<T>(t, control_block_);
205}
206
208
209} // namespace pw
210
211// TODO(b/402489948): Remove when portable atomics are provided by `pw_atomic`.
212#endif // PW_ALLOCATOR_HAS_ATOMICS
Definition: allocator.h:36
Definition: shared_ptr.h:59
Definition: weak_ptr.h:37
WeakPtr(WeakPtr< U > &&other) noexcept
Definition: weak_ptr.h:78
WeakPtr(const WeakPtr &other) noexcept
Copy-constructs a WeakPtr<T> from a WeakPtr<T>.
Definition: weak_ptr.h:52
WeakPtr & operator=(const SharedPtr< U > &other) noexcept
int32_t use_count() const noexcept
Definition: weak_ptr.h:124
WeakPtr(const WeakPtr< U > &other) noexcept
Definition: weak_ptr.h:59
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:85
WeakPtr(const SharedPtr< U > &other) noexcept
Definition: weak_ptr.h:68
constexpr WeakPtr() noexcept=default
Creates an empty (nullptr) instance.
bool expired() const noexcept
Definition: weak_ptr.h:130
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:118
bool owner_before(const PtrType &other) const noexcept
Definition: weak_ptr.h:139
void reset() noexcept
Definition: weak_ptr.h:187
SharedPtr< T > Lock() const noexcept
Definition: weak_ptr.h:198
The Pigweed namespace.
Definition: alignment.h:27