blob: 54d9ef3781291f848a7a3e318113dfb9a042c834 [file] [log] [blame]
Brian Silverman355f11d2018-08-04 23:57:00 -07001#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
21namespace boost
22{
23
24template<class T> class weak_ptr
25{
26private:
27
28 // Borland 5.5.1 specific workarounds
29 typedef weak_ptr<T> this_type;
30
31public:
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
230private:
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
242template<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
247template<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