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