Pigweed
 
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 <cstddef>
17#include <utility>
18
19#include "pw_allocator/internal/control_block.h"
20#include "pw_allocator/internal/managed_ptr.h"
21#include "pw_allocator/shared_ptr.h"
22
23namespace pw {
24
29template <typename T>
30class WeakPtr final : public ::pw::allocator::internal::WeakManagedPtr<T> {
31 private:
32 using Base = ::pw::allocator::internal::WeakManagedPtr<T>;
33 using ControlBlock = ::pw::allocator::internal::ControlBlock;
34
35 public:
36 using element_type = typename Base::element_type;
37
39 constexpr WeakPtr() noexcept = default;
40
42 constexpr WeakPtr(std::nullptr_t) noexcept : WeakPtr() {}
43
45 WeakPtr(const WeakPtr& other) noexcept { *this = other; }
46
51 template <typename U>
52 WeakPtr(const WeakPtr<U>& other) noexcept {
53 *this = other;
54 }
55
60 template <typename U>
61 WeakPtr(const SharedPtr<U>& other) noexcept {
62 *this = other;
63 }
64
70 template <typename U>
71 WeakPtr(WeakPtr<U>&& other) noexcept {
72 *this = other;
73 }
74
75 ~WeakPtr() { reset(); }
76
78 constexpr WeakPtr& operator=(const WeakPtr& other) noexcept {
79 operator= <T>(other);
80 return *this;
81 }
82
87 template <typename U>
88 WeakPtr& operator=(const WeakPtr<U>& other) noexcept;
89
94 template <typename U>
95 WeakPtr& operator=(const SharedPtr<U>& other) noexcept;
96
101 template <typename U>
102 WeakPtr& operator=(WeakPtr<U>&& other) noexcept;
103
108 void reset() noexcept;
109
111 void swap(WeakPtr& other) noexcept {
112 std::swap(control_block_, other.control_block_);
113 }
114
117 uint32_t use_count() const noexcept {
118 return control_block_ == nullptr ? 0 : control_block_->num_shared();
119 }
120
123 bool expired() const noexcept { return use_count() == 0; }
124
127 SharedPtr<T> Lock() const noexcept;
128
131 template <typename PtrType>
132 bool owner_before(const PtrType& other) const noexcept {
133 return control_block_ < other.control_block();
134 }
135
136 private:
137 // Allow WeakPtr<T> to access WeakPtr<U> and vice versa.
138 template <typename>
139 friend class WeakPtr;
140
141 ControlBlock* control_block() const { return control_block_; }
142
143 ControlBlock* control_block_ = nullptr;
144};
145
146// Template implementations.
147
148template <typename T>
149template <typename U>
150WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& other) noexcept {
151 Base::template CheckAssignable<U>();
152 control_block_ = other.control_block_;
153 if (control_block_ != nullptr) {
154 control_block_->IncrementWeak();
155 }
156 return *this;
157}
158
159template <typename T>
160template <typename U>
161WeakPtr<T>& WeakPtr<T>::operator=(const SharedPtr<U>& other) noexcept {
162 Base::template CheckAssignable<U>();
163 control_block_ = other.control_block_;
164 if (control_block_ != nullptr) {
165 control_block_->IncrementWeak();
166 }
167 return *this;
168}
169
170template <typename T>
171template <typename U>
172WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& other) noexcept {
173 Base::template CheckAssignable<U>();
174 control_block_ = other.control_block_;
175 other.control_block_ = nullptr;
176 return *this;
177}
178
179template <typename T>
180void WeakPtr<T>::reset() noexcept {
181 if (control_block_ == nullptr ||
182 control_block_->DecrementWeak() != ControlBlock::Action::kFree) {
183 return;
184 }
185 Allocator* allocator = control_block_->allocator();
186 Base::Deallocate(allocator, control_block_);
187 control_block_ = nullptr;
188}
189
190template <typename T>
192 if (control_block_ == nullptr || !control_block_->IncrementShared()) {
193 return SharedPtr<T>();
194 }
195 void* data = control_block_->data();
196 auto* t = std::launder(reinterpret_cast<element_type*>(data));
197 return SharedPtr<T>(t, control_block_);
198}
199
200} // namespace pw
Definition: allocator.h:34
Definition: shared_ptr.h:44
Definition: weak_ptr.h:30
void reset() noexcept
Definition: weak_ptr.h:180
WeakPtr(WeakPtr< U > &&other) noexcept
Definition: weak_ptr.h:71
uint32_t use_count() const noexcept
Definition: weak_ptr.h:117
WeakPtr(const WeakPtr &other) noexcept
Copy-constructs a WeakPtr<T> from a WeakPtr<T>.
Definition: weak_ptr.h:45
WeakPtr & operator=(const SharedPtr< U > &other) noexcept
WeakPtr(const WeakPtr< U > &other) noexcept
Definition: weak_ptr.h:52
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:78
SharedPtr< T > Lock() const noexcept
Definition: weak_ptr.h:191
WeakPtr(const SharedPtr< U > &other) noexcept
Definition: weak_ptr.h:61
constexpr WeakPtr() noexcept=default
Creates an empty (nullptr) instance.
bool expired() const noexcept
Definition: weak_ptr.h:123
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:111
bool owner_before(const PtrType &other) const noexcept
Definition: weak_ptr.h:132
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27