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