Line data Source code
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 <memory>
19 : #include <cstddef>
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 119848 : constexpr weak_ptr() noexcept : px(0), pn()
36 59924 : {
37 119848 : }
38 :
39 : // generated copy constructor, assignment, destructor are fine...
40 : // ... except in C++0x, move disables the implicit copy
41 :
42 99322 : weak_ptr( weak_ptr const & r ) noexcept : px( r.px ), pn( r.pn )
43 49661 : {
44 99322 : }
45 :
46 : weak_ptr & operator=( weak_ptr const & r ) noexcept
47 : {
48 : px = r.px;
49 : pn = r.pn;
50 : return *this;
51 : }
52 :
53 : //
54 : // The "obvious" converting constructor implementation:
55 : //
56 : // template<class Y>
57 : // weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn)
58 : // {
59 : // }
60 : //
61 : // has a serious problem.
62 : //
63 : // r.px may already have been invalidated. The px(r.px)
64 : // conversion may require access to *r.px (virtual inheritance).
65 : //
66 : // It is not possible to avoid spurious access violations since
67 : // in multithreaded programs r.px may be invalidated at any point.
68 : //
69 :
70 : template<class Y>
71 : weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
72 : noexcept : px(r.lock().get()), pn(r.pn)
73 : {
74 : boost::detail::sp_assert_convertible< Y, T >();
75 : }
76 :
77 : template<class Y>
78 : weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
79 : noexcept : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
80 : {
81 : boost::detail::sp_assert_convertible< Y, T >();
82 : r.px = 0;
83 : }
84 :
85 : // for better efficiency in the T == Y case
86 160728 : weak_ptr( weak_ptr && r )
87 80364 : noexcept : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
88 80364 : {
89 80364 : r.px = 0;
90 160728 : }
91 :
92 : // for better efficiency in the T == Y case
93 14084 : weak_ptr & operator=( weak_ptr && r ) noexcept
94 : {
95 14084 : this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
96 14084 : return *this;
97 : }
98 :
99 :
100 : template<class Y>
101 86066 : weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
102 43033 : noexcept : px( r.px ), pn( r.pn )
103 43033 : {
104 43033 : boost::detail::sp_assert_convertible< Y, T >();
105 86066 : }
106 :
107 : // aliasing
108 : template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept: px( p ), pn( r.pn )
109 : {
110 : }
111 :
112 : template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept: px( p ), pn( r.pn )
113 : {
114 : }
115 :
116 : template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept: px( p ), pn( std::move( r.pn ) )
117 : {
118 : }
119 :
120 : template<class Y>
121 : weak_ptr & operator=( weak_ptr<Y> const & r ) noexcept
122 : {
123 : boost::detail::sp_assert_convertible< Y, T >();
124 :
125 : px = r.lock().get();
126 : pn = r.pn;
127 :
128 : return *this;
129 : }
130 :
131 : template<class Y>
132 : weak_ptr & operator=( weak_ptr<Y> && r ) noexcept
133 : {
134 : this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
135 : return *this;
136 : }
137 :
138 : template<class Y>
139 : weak_ptr & operator=( shared_ptr<Y> const & r ) noexcept
140 : {
141 : boost::detail::sp_assert_convertible< Y, T >();
142 :
143 : px = r.px;
144 : pn = r.pn;
145 :
146 : return *this;
147 : }
148 :
149 215392 : shared_ptr<T> lock() const noexcept
150 : {
151 215392 : return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
152 : }
153 :
154 : long use_count() const noexcept
155 : {
156 : return pn.use_count();
157 : }
158 :
159 481295 : bool expired() const noexcept
160 : {
161 481295 : return pn.use_count() == 0;
162 : }
163 :
164 : bool _empty() const noexcept // extension, not in std::weak_ptr
165 : {
166 : return pn.empty();
167 : }
168 :
169 : bool empty() const noexcept // extension, not in std::weak_ptr
170 : {
171 : return pn.empty();
172 : }
173 :
174 14084 : void reset() noexcept
175 : {
176 14084 : this_type().swap(*this);
177 14084 : }
178 :
179 28168 : void swap(this_type & other) noexcept
180 : {
181 28168 : std::swap(px, other.px);
182 28168 : pn.swap(other.pn);
183 28168 : }
184 :
185 : template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const noexcept
186 : {
187 : return pn < rhs.pn;
188 : }
189 :
190 : template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const noexcept
191 : {
192 : return pn < rhs.pn;
193 : }
194 :
195 : template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const noexcept
196 : {
197 : return pn == rhs.pn;
198 : }
199 :
200 : template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const noexcept
201 : {
202 : return pn == rhs.pn;
203 : }
204 :
205 : std::size_t owner_hash_value() const noexcept
206 : {
207 : return pn.hash_value();
208 : }
209 :
210 : private:
211 :
212 : template<class Y> friend class weak_ptr;
213 : template<class Y> friend class shared_ptr;
214 :
215 : element_type * px; // contained pointer
216 : boost::detail::weak_count pn; // reference counter
217 :
218 : }; // weak_ptr
219 :
220 : template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept
221 : {
222 : return a.owner_before( b );
223 : }
224 :
225 : template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept
226 : {
227 : a.swap(b);
228 : }
229 :
230 : #if defined(__cpp_deduction_guides)
231 :
232 : template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>;
233 :
234 : #endif
235 :
236 : // hash_value
237 :
238 : template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) noexcept
239 : {
240 : return p.owner_hash_value();
241 : }
242 :
243 : } // namespace boost
244 :
245 : // std::hash, std::equal_to
246 :
247 : namespace std
248 : {
249 :
250 : template<class T> struct hash< ::boost::weak_ptr<T> >
251 : {
252 : std::size_t operator()( ::boost::weak_ptr<T> const & p ) const noexcept
253 : {
254 : return p.owner_hash_value();
255 : }
256 : };
257 :
258 : template<class T> struct equal_to< ::boost::weak_ptr<T> >
259 : {
260 : bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const noexcept
261 : {
262 : return a.owner_equals( b );
263 : }
264 : };
265 :
266 : } // namespace std
267 :
268 : #endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
|