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