|
1 #ifndef BOOST_WEAK_PTR_HPP_INCLUDED |
|
2 #define BOOST_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/detail/shared_count.hpp> |
|
18 #include <boost/shared_ptr.hpp> |
|
19 |
|
20 #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash |
|
21 # pragma warning(push) |
|
22 # pragma warning(disable:4284) // odd return type for operator-> |
|
23 #endif |
|
24 |
|
25 namespace boost |
|
26 { |
|
27 |
|
28 template<class T> class weak_ptr |
|
29 { |
|
30 private: |
|
31 |
|
32 // Borland 5.5.1 specific workarounds |
|
33 typedef weak_ptr<T> this_type; |
|
34 |
|
35 public: |
|
36 |
|
37 typedef T element_type; |
|
38 |
|
39 weak_ptr(): px(0), pn() // never throws in 1.30+ |
|
40 { |
|
41 } |
|
42 |
|
43 // generated copy constructor, assignment, destructor are fine |
|
44 |
|
45 |
|
46 // |
|
47 // The "obvious" converting constructor implementation: |
|
48 // |
|
49 // template<class Y> |
|
50 // weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws |
|
51 // { |
|
52 // } |
|
53 // |
|
54 // has a serious problem. |
|
55 // |
|
56 // r.px may already have been invalidated. The px(r.px) |
|
57 // conversion may require access to *r.px (virtual inheritance). |
|
58 // |
|
59 // It is not possible to avoid spurious access violations since |
|
60 // in multithreaded programs r.px may be invalidated at any point. |
|
61 // |
|
62 |
|
63 template<class Y> |
|
64 weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws |
|
65 { |
|
66 px = r.lock().get(); |
|
67 } |
|
68 |
|
69 template<class Y> |
|
70 weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws |
|
71 { |
|
72 } |
|
73 |
|
74 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) |
|
75 |
|
76 template<class Y> |
|
77 weak_ptr & operator=(weak_ptr<Y> const & r) // never throws |
|
78 { |
|
79 px = r.lock().get(); |
|
80 pn = r.pn; |
|
81 return *this; |
|
82 } |
|
83 |
|
84 template<class Y> |
|
85 weak_ptr & operator=(shared_ptr<Y> const & r) // never throws |
|
86 { |
|
87 px = r.px; |
|
88 pn = r.pn; |
|
89 return *this; |
|
90 } |
|
91 |
|
92 #endif |
|
93 |
|
94 shared_ptr<T> lock() const // never throws |
|
95 { |
|
96 #if defined(BOOST_HAS_THREADS) |
|
97 |
|
98 // optimization: avoid throw overhead |
|
99 if(expired()) |
|
100 { |
|
101 return shared_ptr<element_type>(); |
|
102 } |
|
103 |
|
104 try |
|
105 { |
|
106 return shared_ptr<element_type>(*this); |
|
107 } |
|
108 catch(bad_weak_ptr const &) |
|
109 { |
|
110 // Q: how can we get here? |
|
111 // A: another thread may have invalidated r after the use_count test above. |
|
112 return shared_ptr<element_type>(); |
|
113 } |
|
114 |
|
115 #else |
|
116 |
|
117 // optimization: avoid try/catch overhead when single threaded |
|
118 return expired()? shared_ptr<element_type>(): shared_ptr<element_type>(*this); |
|
119 |
|
120 #endif |
|
121 } |
|
122 |
|
123 long use_count() const // never throws |
|
124 { |
|
125 return pn.use_count(); |
|
126 } |
|
127 |
|
128 bool expired() const // never throws |
|
129 { |
|
130 return pn.use_count() == 0; |
|
131 } |
|
132 |
|
133 void reset() // never throws in 1.30+ |
|
134 { |
|
135 this_type().swap(*this); |
|
136 } |
|
137 |
|
138 void swap(this_type & other) // never throws |
|
139 { |
|
140 std::swap(px, other.px); |
|
141 pn.swap(other.pn); |
|
142 } |
|
143 |
|
144 void _internal_assign(T * px2, boost::detail::shared_count const & pn2) |
|
145 { |
|
146 px = px2; |
|
147 pn = pn2; |
|
148 } |
|
149 |
|
150 template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const |
|
151 { |
|
152 return pn < rhs.pn; |
|
153 } |
|
154 |
|
155 // Tasteless as this may seem, making all members public allows member templates |
|
156 // to work in the absence of member template friends. (Matthew Langston) |
|
157 |
|
158 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
|
159 |
|
160 private: |
|
161 |
|
162 template<class Y> friend class weak_ptr; |
|
163 template<class Y> friend class shared_ptr; |
|
164 |
|
165 #endif |
|
166 |
|
167 T * px; // contained pointer |
|
168 boost::detail::weak_count pn; // reference counter |
|
169 |
|
170 }; // weak_ptr |
|
171 |
|
172 template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) |
|
173 { |
|
174 return a._internal_less(b); |
|
175 } |
|
176 |
|
177 template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) |
|
178 { |
|
179 a.swap(b); |
|
180 } |
|
181 |
|
182 // deprecated, provided for backward compatibility |
|
183 template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r) |
|
184 { |
|
185 return r.lock(); |
|
186 } |
|
187 |
|
188 } // namespace boost |
|
189 |
|
190 #ifdef BOOST_MSVC |
|
191 # pragma warning(pop) |
|
192 #endif |
|
193 |
|
194 #endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED |