1 /**
2 * Copyright 2021 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef MINDSPORE_CORE_MINDAPI_BASE_SHARED_PTR_H_
18 #define MINDSPORE_CORE_MINDAPI_BASE_SHARED_PTR_H_
19
20 #include <cstdint>
21 #include <memory>
22 #include <utility>
23 #include <ostream>
24 #include <functional>
25
26 namespace mindspore::api {
27 /// \brief SharedPtr wraps a std::shared_ptr and provides wrapper functions according the underlying implementation.
28 template <typename T>
29 class SharedPtr {
30 public:
31 using element_type = T;
32 constexpr SharedPtr() noexcept = default;
SharedPtr(std::nullptr_t)33 constexpr SharedPtr(std::nullptr_t) noexcept : SharedPtr() {} // NOLINT
34 template <typename U>
SharedPtr(std::shared_ptr<U> && ptr)35 explicit SharedPtr(std::shared_ptr<U> &&ptr) : ptr_(std::move(ptr)) {}
36 template <typename U>
SharedPtr(const SharedPtr<U> & other)37 SharedPtr(const SharedPtr<U> &other) : ptr_(other.ptr_) {}
38 template <typename U>
SharedPtr(SharedPtr<U> && other)39 SharedPtr(SharedPtr<U> &&other) : ptr_(std::move(other.ptr_)) {}
40 template <typename U>
41 SharedPtr &operator=(const SharedPtr<U> &other) {
42 ptr_ = other.ptr_;
43 return *this;
44 }
45 template <typename U>
46 SharedPtr &operator=(SharedPtr<U> &&other) {
47 ptr_ = std::move(other.ptr_);
48 return *this;
49 }
50 ~SharedPtr() = default;
51
addr()52 std::uintptr_t addr() const { return (ptr_ == nullptr) ? 0 : reinterpret_cast<std::uintptr_t>(ptr_->impl().get()); }
53 element_type &operator*() const noexcept { return *ptr_; }
54 element_type *operator->() const noexcept { return ptr_.get(); }
get()55 element_type *get() const noexcept { return ptr_.get(); }
56 explicit operator bool() const { return addr() != 0; }
57
58 private:
59 template <typename U>
60 friend class SharedPtr;
61 std::shared_ptr<element_type> ptr_;
62 };
63
64 template <typename T, typename U>
65 inline bool operator==(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
66 return a.addr() == b.addr();
67 }
68
69 template <typename T>
70 inline bool operator==(const SharedPtr<T> &a, std::nullptr_t) noexcept {
71 return a.addr() == 0;
72 }
73
74 template <typename T>
75 inline bool operator==(std::nullptr_t, const SharedPtr<T> &a) noexcept {
76 return a.addr() == 0;
77 }
78
79 template <typename T, typename U>
80 inline bool operator!=(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
81 return a.addr() != b.addr();
82 }
83
84 template <typename T>
85 inline bool operator!=(const SharedPtr<T> &a, std::nullptr_t) noexcept {
86 return a.addr() != 0;
87 }
88
89 template <typename T>
90 inline bool operator!=(std::nullptr_t, const SharedPtr<T> &a) noexcept {
91 return a.addr() != 0;
92 }
93
94 template <typename T, typename U>
95 inline bool operator<(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
96 return a.addr() < b.addr();
97 }
98
99 template <typename T>
100 inline bool operator<(const SharedPtr<T> &a, std::nullptr_t) noexcept {
101 return a.addr() < 0;
102 }
103
104 template <typename T>
105 inline bool operator<(std::nullptr_t, const SharedPtr<T> &a) noexcept {
106 // 'nullptr < ptr' is false only when ptr is nullptr.
107 return a.addr() != 0;
108 }
109
110 template <typename T, typename U>
111 inline bool operator>(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
112 return a.addr() > b.addr();
113 }
114
115 template <typename T>
116 inline bool operator>(const SharedPtr<T> &a, std::nullptr_t) noexcept {
117 return a.addr() > 0;
118 }
119
120 template <typename T>
121 inline bool operator>(std::nullptr_t, const SharedPtr<T> &) noexcept {
122 // 'nullptr > ptr' is always false.
123 return false;
124 }
125
126 template <typename T, typename U>
127 inline bool operator<=(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
128 return a.addr() <= b.addr();
129 }
130
131 template <typename T>
132 inline bool operator<=(const SharedPtr<T> &a, std::nullptr_t) noexcept {
133 return a.addr() <= 0;
134 }
135
136 template <typename T>
137 inline bool operator<=(std::nullptr_t, const SharedPtr<T> &) noexcept {
138 // 'nullptr <= ptr' is always true.
139 return true;
140 }
141
142 template <typename T, typename U>
143 inline bool operator>=(const SharedPtr<T> &a, const SharedPtr<U> &b) noexcept {
144 return a.addr() >= b.addr();
145 }
146
147 template <typename T>
148 inline bool operator>=(const SharedPtr<T> &a, std::nullptr_t) noexcept {
149 return a.addr() >= 0;
150 }
151
152 template <typename T>
153 inline bool operator>=(std::nullptr_t, const SharedPtr<T> &a) noexcept {
154 // 'nullptr >= ptr' is true only when ptr is nullptr.
155 return a.addr() == 0;
156 }
157
158 template <typename T, typename U, typename V>
159 inline std::basic_ostream<U, V> &operator<<(std::basic_ostream<U, V> &os, const SharedPtr<T> &a) {
160 return (os << reinterpret_cast<void *>(a.addr()));
161 }
162
163 /// \brief Constructs an object of type T and wraps it in a SharedPtr.
164 ///
165 /// \param[in] args The parameter list for the constructor of T.
166 template <typename T, typename... Args>
MakeShared(Args &&...args)167 inline SharedPtr<T> MakeShared(Args &&... args) {
168 auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
169 return SharedPtr<T>(std::move(ptr));
170 }
171 } // namespace mindspore::api
172
173 namespace std {
174 template <typename T>
175 struct hash<mindspore::api::SharedPtr<T>> {
176 size_t operator()(const mindspore::api::SharedPtr<T> &ptr) const noexcept { return static_cast<size_t>(ptr.addr()); }
177 };
178 } // namespace std
179
180 #endif // MINDSPORE_CORE_MINDAPI_BASE_SHARED_PTR_H_
181