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