16#include "pw_allocator/config.h"
19#if PW_ALLOCATOR_HAS_ATOMICS
25#include "pw_allocator/deallocator.h"
26#include "pw_allocator/internal/control_block.h"
27#include "pw_allocator/internal/managed_ptr.h"
28#include "pw_allocator/layout.h"
57class SharedPtr final : public ::pw::allocator::internal::ManagedPtr<T> {
59 using Base = ::pw::allocator::internal::ManagedPtr<T>;
60 using ControlBlock = ::pw::allocator::internal::ControlBlock;
63 using element_type =
typename Base::element_type;
100 template <
typename U>
102 *
this = std::move(other);
109 operator= <T>(other);
119 template <
typename U>
128 template <
typename U>
135 SharedPtr& operator=(std::nullptr_t)
noexcept;
141 static_assert(std::is_array_v<T>,
142 "size() cannot be called on non-array types");
143 return control_block_ ==
nullptr ? 0 : control_block_->size();
149 return control_block_ ==
nullptr ? 0 : control_block_->num_shared();
157 void reset() noexcept;
164 template <typename PtrType>
165 bool owner_before(const PtrType& other) const noexcept {
166 return control_block_ < other.control_block();
172 static constexpr bool is_unbounded_array_v =
173 allocator::internal::is_unbounded_array_v<T>;
200 template <
typename... Args>
220 SharedPtr(element_type* value, ControlBlock* control_block)
221 : Base(value), control_block_(control_block) {}
223 ControlBlock* control_block()
const {
return control_block_; }
226 template <
typename U>
227 void CopyFrom(
const SharedPtr<U>& other);
234 template <
typename U>
235 constexpr void CheckArrayTypes();
237 ControlBlock* control_block_ =
nullptr;
243template <
typename... Args>
244SharedPtr<T> SharedPtr<T>::Create(Allocator* allocator, Args&&... args) {
245 static_assert(!std::is_array_v<T>);
246 auto* control_block = ControlBlock::Create(allocator, Layout::Of<T>(), 1);
247 if (control_block ==
nullptr) {
250 auto* t =
new (control_block->data()) T(std::forward<Args>(args)...);
251 return SharedPtr<T>(t, control_block);
255SharedPtr<T> SharedPtr<T>::Create(Allocator* allocator,
258 static_assert(allocator::internal::is_unbounded_array_v<T>);
259 Layout layout = Layout::Of<T>(count).Align(alignment);
260 auto* control_block = ControlBlock::Create(allocator, layout, count);
261 if (control_block ==
nullptr) {
264 auto* t =
new (control_block->data()) std::remove_extent_t<T>[count];
265 return SharedPtr<T>(t, control_block);
271 const SharedPtr<U>& other)
noexcept {
272 CheckArrayTypes<U>();
274 if (control_block_ !=
nullptr) {
275 control_block_->IncrementShared();
283 CheckArrayTypes<U>();
298 if (*
this ==
nullptr) {
301 auto action = control_block_->DecrementShared();
302 if (action == ControlBlock::Action::kNone) {
309 Allocator* allocator = control_block_->allocator();
310 if (!Base::HasCapability(allocator, allocator::kSkipsDestroy)) {
311 if constexpr (std::is_array_v<T>) {
312 Base::Destroy(control_block_->size());
318 if (action == ControlBlock::Action::kExpire) {
321 Base::Resize(allocator, control_block_,
sizeof(ControlBlock));
324 Base::Deallocate(allocator, control_block_);
333 std::swap(control_block_, other.control_block_);
339 CheckArrayTypes<U>();
340 Base::CopyFrom(other);
341 control_block_ = other.control_block_;
345void SharedPtr<T>::Release() {
347 control_block_ =
nullptr;
352constexpr void SharedPtr<T>::CheckArrayTypes() {
353 if constexpr (std::is_array_v<T>) {
354 static_assert(std::is_array_v<U>,
355 "non-array type used with SharedPtr<T[]>");
357 static_assert(!std::is_array_v<U>,
"array type used with SharedPtr<T>");
Definition: allocator.h:34
Definition: multibuf_v2.h:193
Definition: shared_ptr.h:57
SharedPtr(SharedPtr< U > &&other) noexcept
Definition: shared_ptr.h:101
SharedPtr & operator=(SharedPtr< U > &&other) noexcept
size_t size() const
Definition: shared_ptr.h:140
void swap(SharedPtr &other) noexcept
Swaps the managed pointer and deallocator of this and another object.
Definition: shared_ptr.h:331
~SharedPtr()
Releases any currently-held value.
Definition: shared_ptr.h:67
constexpr SharedPtr & operator=(const SharedPtr< U > &other) noexcept
constexpr SharedPtr() noexcept=default
constexpr SharedPtr(const SharedPtr &other) noexcept
Copy-constructs a SharedPtr<T> from a SharedPtr<T>.
Definition: shared_ptr.h:82
int32_t use_count() const
Definition: shared_ptr.h:148
constexpr SharedPtr & operator=(const SharedPtr &other) noexcept
Definition: shared_ptr.h:108
constexpr SharedPtr(const SharedPtr< U > &other) noexcept
Definition: shared_ptr.h:91
void reset() noexcept
Definition: shared_ptr.h:297
Definition: weak_ptr.h:35
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
MultiBufProperty
Basic properties of a MultiBuf.
Definition: properties.h:22