Pigweed
 
Loading...
Searching...
No Matches
unique_ptr.h
1// Copyright 2024 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 <type_traits>
18#include <utility>
19
20#include "pw_allocator/config.h"
21#include "pw_allocator/internal/managed_ptr.h"
22#include "pw_preprocessor/compiler.h"
23
24namespace pw {
25
39template <typename T>
40class UniquePtr : public ::pw::allocator::internal::ManagedPtr<T> {
41 private:
42 using Base = ::pw::allocator::internal::ManagedPtr<T>;
43 using Empty = ::pw::allocator::internal::Empty;
44
45 public:
46 using pointer = typename Base::element_type*;
47 using element_type = typename Base::element_type;
48
53 constexpr UniquePtr() noexcept {
54 if constexpr (std::is_array_v<T>) {
55 size_ = 0;
56 }
57 }
58
63 constexpr UniquePtr(std::nullptr_t) noexcept : UniquePtr() {}
64
70 template <typename U>
71 UniquePtr(UniquePtr<U>&& other) noexcept {
72 *this = std::move(other);
73 }
74
77
84 template <typename U>
85 UniquePtr& operator=(UniquePtr<U>&& other) noexcept;
86
91 UniquePtr& operator=(std::nullptr_t) noexcept;
92
96 size_t size() const {
97 static_assert(std::is_array_v<T>,
98 "size() cannot be called with a non-array type");
99 return size_;
100 }
101
103 Deallocator* deallocator() const { return deallocator_; }
104
109 element_type* Release() noexcept;
110
115 void Reset() noexcept;
116
118 void Swap(UniquePtr& other);
119
120 private:
121 // Allow construction with to the implementation of `MakeUnique`.
122 friend class Deallocator;
123
124 // Allow UniquePtr<T> to access UniquePtr<U> and vice versa.
125 template <typename>
126 friend class UniquePtr;
127
135 UniquePtr(element_type* value, Deallocator* deallocator)
136 : Base(value), deallocator_(deallocator) {}
137
145 UniquePtr(element_type* value, size_t size, Deallocator* deallocator)
146 : Base(value), size_(size), deallocator_(deallocator) {}
147
149 template <typename U>
150 void CopyFrom(const UniquePtr<U>& other);
151
155 PW_NO_UNIQUE_ADDRESS
156 std::conditional_t<std::is_array_v<T>, size_t, Empty> size_;
157
160 Deallocator* deallocator_ = nullptr;
161};
162
163namespace allocator {
164
165// Alias for module consumers using the older name for the above type.
166template <typename T>
167using UniquePtr = PW_ALLOCATOR_DEPRECATED ::pw::UniquePtr<T>;
168
169} // namespace allocator
170
171// Template method implementations.
172
173template <typename T>
174template <typename U>
175UniquePtr<T>& UniquePtr<T>::operator=(UniquePtr<U>&& other) noexcept {
176 Reset();
177 CopyFrom(other);
178 other.Release();
179 return *this;
180}
181
182template <typename T>
183UniquePtr<T>& UniquePtr<T>::operator=(std::nullptr_t) noexcept {
184 Reset();
185 return *this;
186}
187
188template <typename T>
189typename UniquePtr<T>::element_type* UniquePtr<T>::Release() noexcept {
190 element_type* value = Base::Release();
191 deallocator_ = nullptr;
192 return value;
193}
194
195template <typename T>
196void UniquePtr<T>::Reset() noexcept {
197 if (*this == nullptr) {
198 return;
199 }
200 if (!Base::HasCapability(deallocator_, allocator::kSkipsDestroy)) {
201 if constexpr (std::is_array_v<T>) {
202 Base::Destroy(size_);
203 } else {
204 Base::Destroy();
205 }
206 }
207 Deallocator* deallocator = deallocator_;
208 Base::Deallocate(deallocator, Release());
209}
210
211template <typename T>
213 Base::Swap(other);
214 if constexpr (std::is_array_v<T>) {
215 std::swap(size_, other.size_);
216 }
217 std::swap(deallocator_, other.deallocator_);
218}
219
220template <typename T>
221template <typename U>
222void UniquePtr<T>::CopyFrom(const UniquePtr<U>& other) {
223 Base::CopyFrom(other);
224 size_ = other.size_;
225 deallocator_ = other.deallocator_;
226}
227
228} // namespace pw
Abstract interface for releasing memory.
Definition: deallocator.h:26
Definition: unique_ptr.h:40
UniquePtr(UniquePtr< U > &&other) noexcept
Definition: unique_ptr.h:71
element_type * Release() noexcept
Definition: unique_ptr.h:189
Deallocator * deallocator() const
Returns a pointer to the object that can destroy the value.
Definition: unique_ptr.h:103
void Reset() noexcept
Definition: unique_ptr.h:196
constexpr UniquePtr() noexcept
Definition: unique_ptr.h:53
size_t size() const
Definition: unique_ptr.h:96
UniquePtr & operator=(UniquePtr< U > &&other) noexcept
friend class Deallocator
TODO(b/326509341): Remove when downstream consumers migrate.
Definition: unique_ptr.h:122
~UniquePtr()
Frees any currently-held value.
Definition: unique_ptr.h:76
constexpr UniquePtr(std::nullptr_t) noexcept
Definition: unique_ptr.h:63
void Swap(UniquePtr &other)
Swaps the managed pointer and deallocator of this and another object.
Definition: unique_ptr.h:212
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27