]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(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 |