1 | #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
3 | |
4 | // |
5 | // weak_ptr.hpp |
6 | // |
7 | // Copyright (c) 2001, 2002, 2003 Peter Dimov |
8 | // |
9 | // Distributed under the Boost Software License, Version 1.0. (See |
10 | // accompanying file LICENSE_1_0.txt or copy at |
11 | // http://www.boost.org/LICENSE_1_0.txt) |
12 | // |
13 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
14 | // |
15 | |
16 | #include <boost/smart_ptr/detail/requires_cxx11.hpp> |
17 | #include <boost/smart_ptr/detail/shared_count.hpp> |
18 | #include <boost/smart_ptr/shared_ptr.hpp> |
19 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
20 | #include <memory> |
21 | #include <cstddef> |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | template<class T> class weak_ptr |
27 | { |
28 | private: |
29 | |
30 | // Borland 5.5.1 specific workarounds |
31 | typedef weak_ptr<T> this_type; |
32 | |
33 | public: |
34 | |
35 | typedef typename boost::detail::sp_element< T >::type element_type; |
36 | |
37 | BOOST_CONSTEXPR weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() |
38 | { |
39 | } |
40 | |
41 | // generated copy constructor, assignment, destructor are fine... |
42 | |
43 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
44 | |
45 | // ... except in C++0x, move disables the implicit copy |
46 | |
47 | weak_ptr( weak_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
48 | { |
49 | } |
50 | |
51 | weak_ptr & operator=( weak_ptr const & r ) BOOST_SP_NOEXCEPT |
52 | { |
53 | px = r.px; |
54 | pn = r.pn; |
55 | return *this; |
56 | } |
57 | |
58 | #endif |
59 | |
60 | // |
61 | // The "obvious" converting constructor implementation: |
62 | // |
63 | // template<class Y> |
64 | // weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) |
65 | // { |
66 | // } |
67 | // |
68 | // has a serious problem. |
69 | // |
70 | // r.px may already have been invalidated. The px(r.px) |
71 | // conversion may require access to *r.px (virtual inheritance). |
72 | // |
73 | // It is not possible to avoid spurious access violations since |
74 | // in multithreaded programs r.px may be invalidated at any point. |
75 | // |
76 | |
77 | template<class Y> |
78 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
79 | |
80 | weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
81 | |
82 | #else |
83 | |
84 | weak_ptr( weak_ptr<Y> const & r ) |
85 | |
86 | #endif |
87 | BOOST_SP_NOEXCEPT : px(r.lock().get()), pn(r.pn) |
88 | { |
89 | boost::detail::sp_assert_convertible< Y, T >(); |
90 | } |
91 | |
92 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
93 | |
94 | template<class Y> |
95 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
96 | |
97 | weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
98 | |
99 | #else |
100 | |
101 | weak_ptr( weak_ptr<Y> && r ) |
102 | |
103 | #endif |
104 | BOOST_SP_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) |
105 | { |
106 | boost::detail::sp_assert_convertible< Y, T >(); |
107 | r.px = 0; |
108 | } |
109 | |
110 | // for better efficiency in the T == Y case |
111 | weak_ptr( weak_ptr && r ) |
112 | BOOST_SP_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) |
113 | { |
114 | r.px = 0; |
115 | } |
116 | |
117 | // for better efficiency in the T == Y case |
118 | weak_ptr & operator=( weak_ptr && r ) BOOST_SP_NOEXCEPT |
119 | { |
120 | this_type( static_cast< weak_ptr && >( r ) ).swap( *this ); |
121 | return *this; |
122 | } |
123 | |
124 | |
125 | #endif |
126 | |
127 | template<class Y> |
128 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) |
129 | |
130 | weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) |
131 | |
132 | #else |
133 | |
134 | weak_ptr( shared_ptr<Y> const & r ) |
135 | |
136 | #endif |
137 | BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
138 | { |
139 | boost::detail::sp_assert_convertible< Y, T >(); |
140 | } |
141 | |
142 | // aliasing |
143 | template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn ) |
144 | { |
145 | } |
146 | |
147 | template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn ) |
148 | { |
149 | } |
150 | |
151 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
152 | |
153 | template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( std::move( r.pn ) ) |
154 | { |
155 | } |
156 | |
157 | #endif |
158 | |
159 | #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) |
160 | |
161 | template<class Y> |
162 | weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPT |
163 | { |
164 | boost::detail::sp_assert_convertible< Y, T >(); |
165 | |
166 | px = r.lock().get(); |
167 | pn = r.pn; |
168 | |
169 | return *this; |
170 | } |
171 | |
172 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
173 | |
174 | template<class Y> |
175 | weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPT |
176 | { |
177 | this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this ); |
178 | return *this; |
179 | } |
180 | |
181 | #endif |
182 | |
183 | template<class Y> |
184 | weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT |
185 | { |
186 | boost::detail::sp_assert_convertible< Y, T >(); |
187 | |
188 | px = r.px; |
189 | pn = r.pn; |
190 | |
191 | return *this; |
192 | } |
193 | |
194 | #endif |
195 | |
196 | shared_ptr<T> lock() const BOOST_SP_NOEXCEPT |
197 | { |
198 | return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() ); |
199 | } |
200 | |
201 | long use_count() const BOOST_SP_NOEXCEPT |
202 | { |
203 | return pn.use_count(); |
204 | } |
205 | |
206 | bool expired() const BOOST_SP_NOEXCEPT |
207 | { |
208 | return pn.use_count() == 0; |
209 | } |
210 | |
211 | bool _empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr |
212 | { |
213 | return pn.empty(); |
214 | } |
215 | |
216 | bool empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr |
217 | { |
218 | return pn.empty(); |
219 | } |
220 | |
221 | void reset() BOOST_SP_NOEXCEPT |
222 | { |
223 | this_type().swap(*this); |
224 | } |
225 | |
226 | void swap(this_type & other) BOOST_SP_NOEXCEPT |
227 | { |
228 | std::swap(px, other.px); |
229 | pn.swap(r&: other.pn); |
230 | } |
231 | |
232 | template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
233 | { |
234 | return pn < rhs.pn; |
235 | } |
236 | |
237 | template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
238 | { |
239 | return pn < rhs.pn; |
240 | } |
241 | |
242 | template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
243 | { |
244 | return pn == rhs.pn; |
245 | } |
246 | |
247 | template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
248 | { |
249 | return pn == rhs.pn; |
250 | } |
251 | |
252 | std::size_t owner_hash_value() const BOOST_SP_NOEXCEPT |
253 | { |
254 | return pn.hash_value(); |
255 | } |
256 | |
257 | // Tasteless as this may seem, making all members public allows member templates |
258 | // to work in the absence of member template friends. (Matthew Langston) |
259 | |
260 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
261 | |
262 | private: |
263 | |
264 | template<class Y> friend class weak_ptr; |
265 | template<class Y> friend class shared_ptr; |
266 | |
267 | #endif |
268 | |
269 | element_type * px; // contained pointer |
270 | boost::detail::weak_count pn; // reference counter |
271 | |
272 | }; // weak_ptr |
273 | |
274 | template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPT |
275 | { |
276 | return a.owner_before( b ); |
277 | } |
278 | |
279 | template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPT |
280 | { |
281 | a.swap(b); |
282 | } |
283 | |
284 | #if defined(__cpp_deduction_guides) |
285 | |
286 | template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>; |
287 | |
288 | #endif |
289 | |
290 | // hash_value |
291 | |
292 | template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
293 | { |
294 | return p.owner_hash_value(); |
295 | } |
296 | |
297 | } // namespace boost |
298 | |
299 | // std::hash, std::equal_to |
300 | |
301 | namespace std |
302 | { |
303 | |
304 | #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) |
305 | |
306 | template<class T> struct hash< ::boost::weak_ptr<T> > |
307 | { |
308 | std::size_t operator()( ::boost::weak_ptr<T> const & p ) const BOOST_SP_NOEXCEPT |
309 | { |
310 | return p.owner_hash_value(); |
311 | } |
312 | }; |
313 | |
314 | #endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) |
315 | |
316 | template<class T> struct equal_to< ::boost::weak_ptr<T> > |
317 | { |
318 | bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const BOOST_SP_NOEXCEPT |
319 | { |
320 | return a.owner_equals( b ); |
321 | } |
322 | }; |
323 | |
324 | } // namespace std |
325 | |
326 | #endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED |
327 | |