1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://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,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef MAPLE_UTIL_SAFE_PTR_H
17 #define MAPLE_UTIL_SAFE_PTR_H
18 #include "mpl_logging.h"
19 #include "ptr.h"
20
21 namespace maple {
22 namespace utils {
23 template <typename T>
AssertNotNull(const T *ptr)24 inline void AssertNotNull(const T *ptr)
25 {
26 CHECK_FATAL(ptr != nullptr, "nullptr was assigned to SafePtr.");
27 }
28
29 template <typename T>
30 class SafePtr {
31 using Base = Ptr<T, AssertNotNull<T>>;
32
33 public:
34 using pointer = typename Base::Pointer;
35 using ElementType = typename Base::ElementType;
36
37 constexpr SafePtr() noexcept = delete;
38
39 constexpr SafePtr(std::nullptr_t) noexcept = delete;
40
SafePtr(pointer ptr)41 SafePtr(pointer ptr) : base(ptr) {}
42
SafePtr(T &ref)43 SafePtr(T &ref) : base(ref, CheckNothing<T>) {}
44
45 SafePtr(T &&ref) = delete;
46
47 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
SafePtr(U *ptr)48 SafePtr(U *ptr) : base(ptr)
49 {
50 }
51
52 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
SafePtr(U &ref)53 SafePtr(U &ref) : base(ref, CheckNothing<T>)
54 {
55 }
56
57 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
58 SafePtr(U &&ref) = delete;
59
SafePtr(const SafePtr &other)60 SafePtr(const SafePtr &other) : base(other.base) {}
61
move(other.base)62 SafePtr(SafePtr &&other) noexcept : base(std::move(other.base)) {}
63
64 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
SafePtr(const SafePtr<U> &other)65 explicit SafePtr(const SafePtr<U> &other) : base(other.get(), CheckNothing<T>)
66 {
67 }
68
69 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
SafePtr(SafePtr<U> &&other)70 explicit SafePtr(SafePtr<U> &&other) : base(other.get(), CheckNothing<T>)
71 {
72 }
73
74 ~SafePtr() = default;
75
76 SafePtr &operator=(pointer ptr) noexcept
77 {
78 base = ptr;
79 return *this;
80 }
81
82 SafePtr &operator=(std::nullptr_t) noexcept = delete;
83
84 SafePtr &operator=(const SafePtr &ptr) noexcept
85 {
86 base = ptr.base;
87 return *this;
88 }
89
90 SafePtr &operator=(SafePtr &&ptr) noexcept
91 {
92 base = std::move(ptr.base);
93 return *this;
94 }
95
96 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
97 SafePtr &operator=(const SafePtr<U> &ptr) noexcept
98 {
99 base = Base(static_cast<T *>(ptr.get()), CheckNothing<T>);
100 return *this;
101 }
102
103 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
104 SafePtr &operator=(SafePtr<U> &&ptr) noexcept
105 {
106 base = Base(static_cast<T *>(ptr.get()), CheckNothing<T>);
107 return *this;
108 }
109
110 pointer release() noexcept = delete;
111
112 void reset(std::nullptr_t) noexcept = delete;
113
114 void reset(pointer ptr) noexcept
115 {
116 AssertNotNull(ptr);
117 base.reset(ptr);
118 }
119
120 void swap(SafePtr &other) noexcept
121 {
122 std::swap(base, other.base);
123 }
124
125 T *get() const noexcept
126 {
127 return base.get();
128 }
129
130 explicit operator bool() const noexcept = delete;
131
operator *() const132 T &operator*() const
133 {
134 return *get();
135 }
136
137 T *operator->() const noexcept
138 {
139 return get();
140 }
141
142 SafePtr &operator++() = delete;
143
144 const SafePtr operator++(int) = delete;
145
146 SafePtr &operator--() = delete;
147
148 const SafePtr operator--(int) = delete;
149
150 SafePtr &operator+=(std::ptrdiff_t) = delete;
151
152 SafePtr &operator-=(std::ptrdiff_t) = delete;
153
154 private:
155 Base base;
156 };
157
158 template <typename T, typename U>
operator ==(const SafePtr<T> &lhs, const SafePtr<U> &rhs)159 inline bool operator==(const SafePtr<T> &lhs, const SafePtr<U> &rhs)
160 {
161 return lhs.get() == rhs.get();
162 }
163
164 template <typename T, typename U>
operator !=(const SafePtr<T> &lhs, const SafePtr<U> &rhs)165 inline bool operator!=(const SafePtr<T> &lhs, const SafePtr<U> &rhs)
166 {
167 return !(lhs == rhs);
168 }
169
170 template <typename T, typename U>
171 inline bool operator<(const SafePtr<T> &lhs, const SafePtr<U> &rhs) = delete;
172
173 template <typename T, typename U>
174 inline bool operator<=(const SafePtr<T> &lhs, const SafePtr<U> &rhs) = delete;
175
176 template <typename T, typename U>
177 inline bool operator>(const SafePtr<T> &lhs, const SafePtr<U> &rhs) = delete;
178
179 template <typename T, typename U>
180 inline bool operator>=(const SafePtr<T> &lhs, const SafePtr<U> &rhs) = delete;
181
182 template <typename T>
183 inline bool operator==(const SafePtr<T> &lhs, std::nullptr_t) = delete;
184
185 template <typename T>
186 inline bool operator==(std::nullptr_t, const SafePtr<T> &rhs) = delete;
187
188 template <typename T>
189 inline bool operator!=(const SafePtr<T> &lhs, std::nullptr_t) = delete;
190
191 template <typename T>
192 inline bool operator!=(std::nullptr_t, const SafePtr<T> &rhs) = delete;
193
194 template <typename T>
195 inline bool operator<(const SafePtr<T> &lhs, std::nullptr_t) = delete;
196
197 template <typename T>
198 inline bool operator<(std::nullptr_t, const SafePtr<T> &rhs) = delete;
199
200 template <typename T>
201 inline bool operator<=(const SafePtr<T> &lhs, std::nullptr_t) = delete;
202
203 template <typename T>
204 inline bool operator<=(std::nullptr_t, const SafePtr<T> &rhs) = delete;
205
206 template <typename T>
207 inline bool operator>(const SafePtr<T> &lhs, std::nullptr_t) = delete;
208
209 template <typename T>
210 inline bool operator>(std::nullptr_t, const SafePtr<T> &rhs) = delete;
211
212 template <typename T>
213 inline bool operator>=(const SafePtr<T> &lhs, std::nullptr_t) = delete;
214
215 template <typename T>
216 inline bool operator>=(std::nullptr_t, const SafePtr<T> &rhs) = delete;
217
218 template <typename T>
ToRef(SafePtr<T> ptr)219 inline T &ToRef(SafePtr<T> ptr)
220 {
221 return *ptr;
222 }
223 } // namespace utils
224 } // namespace maple
225
226 namespace std {
227 template <class T>
228 struct hash<maple::utils::SafePtr<T>> {
operator ()std::hash229 std::size_t operator()(const maple::utils::SafePtr<T> &safePtr) const
230 {
231 return hash<typename maple::utils::SafePtr<T>::pointer>()(safePtr.get());
232 }
233 };
234 } // namespace std
235 #endif // DIY_CPLUSPLUS_SAFE_PTR_H
236