diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 29e7e9f..d44b201 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -24,8 +24,6 @@ namespace boost { -template shared_ptr get_shared_ptr(weak_ptr const & r); // never throws - template class weak_ptr { private: @@ -64,7 +62,7 @@ public: template weak_ptr(weak_ptr const & r): pn(r.pn) // never throws { - px = boost::get_shared_ptr(r).get(); + px = r.lock().get(); } template @@ -77,7 +75,7 @@ public: template weak_ptr & operator=(weak_ptr const & r) // never throws { - px = boost::get_shared_ptr(r).get(); + px = r.lock().get(); pn = r.pn; return *this; } @@ -92,9 +90,33 @@ public: #endif - void reset() // never throws in 1.30+ + shared_ptr lock() const // never throws { - this_type().swap(*this); +#if defined(BOOST_HAS_THREADS) + + // optimization: avoid throw overhead + if(expired()) + { + return shared_ptr(); + } + + try + { + return shared_ptr(*this); + } + catch(bad_weak_ptr const &) + { + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. + return shared_ptr(); + } + +#else + + // optimization: avoid try/catch overhead when single threaded + return expired()? shared_ptr(): shared_ptr(*this); + +#endif } long use_count() const // never throws @@ -107,6 +129,11 @@ public: return pn.use_count() == 0; } + void reset() // never throws in 1.30+ + { + this_type().swap(*this); + } + void swap(this_type & other) // never throws { std::swap(px, other.px); @@ -151,39 +178,10 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } -template shared_ptr get_shared_ptr(weak_ptr const & r) // never throws -{ -#if defined(BOOST_HAS_THREADS) - - // optimization: avoid throw overhead - if(r.use_count() == 0) - { - return shared_ptr(); - } - - try - { - return shared_ptr(r); - } - catch(bad_weak_ptr const &) - { - // Q: how can we get here? - // A: another thread may have invalidated r after the use_count test above. - return shared_ptr(); - } - -#else - - // optimization: avoid try/catch overhead when single threaded - return r.use_count() == 0? shared_ptr(): shared_ptr(r); - -#endif -} - // deprecated, provided for backward compatibility template shared_ptr make_shared(weak_ptr const & r) { - return boost::get_shared_ptr(r); + return r.lock(); } } // namespace boost diff --git a/shared_ptr.htm b/shared_ptr.htm index bdd8d22..4e5f561 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -390,8 +390,8 @@ q = p; many of the implicit conversion pitfalls.

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using dynamic_pointer_cast or - get_shared_ptr.]

+ to be declared in conditions when using dynamic_pointer_cast or + weak_ptr::lock.]

swap

void swap(shared_ptr & b); // never throws
diff --git a/sp_techniques.html b/sp_techniques.html index aa104ab..59159a2 100644 --- a/sp_techniques.html +++ b/sp_techniques.html @@ -413,7 +413,7 @@ public: virtual shared_ptr<X> getX() { - shared_ptr<X> px = get_shared_ptr(weak_this); + shared_ptr<X> px = weak_this.lock(); return px; } }; diff --git a/test/shared_ptr_basic_test.cpp b/test/shared_ptr_basic_test.cpp index db5c0c1..1b9c3cc 100644 --- a/test/shared_ptr_basic_test.cpp +++ b/test/shared_ptr_basic_test.cpp @@ -94,7 +94,7 @@ template void test_is_Y(boost::shared_ptr const & p) template void test_is_Y(boost::weak_ptr const & p) { - boost::shared_ptr q = boost::get_shared_ptr(p); + boost::shared_ptr q = p.lock(); BOOST_TEST(q.get() != 0); BOOST_TEST(q->id() == 2); } @@ -221,7 +221,7 @@ int main() { } - test_is_zero(boost::get_shared_ptr(wp1)); + test_is_zero(wp1.lock()); weak_ptr wp2 = static_pointer_cast(p5); @@ -232,10 +232,10 @@ int main() // Scoped to not affect the subsequent use_count() tests. { shared_ptr sp2(wp2); - test_is_nonzero(boost::get_shared_ptr(wp2)); + test_is_nonzero(wp2.lock()); } - weak_ptr wp3 = dynamic_pointer_cast(boost::get_shared_ptr(wp2)); + weak_ptr wp3 = dynamic_pointer_cast(wp2.lock()); BOOST_TEST(wp3.use_count() == 1); test_shared(wp2, wp3); @@ -246,7 +246,7 @@ int main() test_shared(wp2, wp4); wp1 = p2; - test_is_zero(boost::get_shared_ptr(wp1)); + test_is_zero(wp1.lock()); wp1 = p4; wp1 = wp3; diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index 7525d7a..447dd9c 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -3094,7 +3094,7 @@ public: virtual boost::shared_ptr getX() { - boost::shared_ptr px = boost::get_shared_ptr(weak_this); + boost::shared_ptr px = weak_this.lock(); return px; } }; diff --git a/test/weak_ptr_test.cpp b/test/weak_ptr_test.cpp index 7408bb9..098d32d 100644 --- a/test/weak_ptr_test.cpp +++ b/test/weak_ptr_test.cpp @@ -1183,14 +1183,14 @@ void test() } // namespace n_comparison -namespace n_get_shared_ptr +namespace n_lock { void test() { } -} // namespace n_get_shared_ptr +} // namespace n_lock namespace n_map { @@ -1272,7 +1272,7 @@ int main() n_use_count::test(); n_swap::test(); n_comparison::test(); - n_get_shared_ptr::test(); + n_lock::test(); n_map::test(); diff --git a/weak_ptr.htm b/weak_ptr.htm index e8dd32d..fb9f44f 100644 --- a/weak_ptr.htm +++ b/weak_ptr.htm @@ -17,12 +17,12 @@

The weak_ptr class template stores a "weak reference" to an object that's already managed by a shared_ptr. To access the object, a weak_ptr can be converted to a shared_ptr using - the shared_ptr constructor or the function - get_shared_ptr. When the last shared_ptr to the - object goes away and the object is deleted, the attempt to obtain a shared_ptr + the shared_ptr constructor or the member function + lock. When the last shared_ptr to the object goes + away and the object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, - and get_shared_ptr will return an empty shared_ptr.

+ and weak_ptr::lock will return an empty shared_ptr.

Every weak_ptr meets the CopyConstructible and Assignable requirements of the C++ Standard Library, and so can be used in standard library containers. Comparison operators are supplied so that weak_ptr works with the @@ -33,7 +33,8 @@

Compared to shared_ptr, weak_ptr provides a very limited subset of operations since accessing its stored pointer is often dangerous in multithreaded programs, and sometimes unsafe even within a single - thread (that is, it may invoke undefined behavior.) Consider, for example, this + thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr + has a get member function that returns a raw pointer, and consider this innocent piece of code:

shared_ptr<int> p(new int(5));
 weak_ptr<int> q(p);
@@ -55,14 +56,16 @@ weak_ptr<int> q(p);
 
 // some time later
 
-if(shared_ptr<int> r = get_shared_ptr(q))
+if(shared_ptr<int> r = q.lock())
 {
     // use *r
 }
 

Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will - stay alive until r goes out of scope (or is reset.)

+ stay alive until r goes out of scope or is reset. By obtaining + a shared_ptr to the object, we have effectively locked it + against destruction.

Synopsis

namespace boost {
 
@@ -83,11 +86,11 @@ if(shared_ptr<int> r = get_shared_ptr(q))
       template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
       template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
 
-      void reset();
-
       long use_count() const;
       bool expired() const;
+      shared_ptr<T> lock() const;
 
+      void reset();
       void swap(weak_ptr<T> & b);
   };
 
@@ -96,10 +99,6 @@ if(shared_ptr<int> r = get_shared_ptr(q))
 
   template<class T>
     void swap(weak_ptr<T> & a, weak_ptr<T> & b);
-
-  template<class T>
-    shared_ptr<T> get_shared_ptr(weak_ptr<T> const & r);
-
 }
 

Members

@@ -143,11 +142,6 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

Notes: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.

-

reset

-
void reset();
-
-

Effects: Equivalent to weak_ptr().swap(*this).

-

use_count

long use_count() const;
@@ -165,6 +159,17 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

Throws: nothing.

Notes: expired() may be faster than use_count().

+

lock

+
shared_ptr<T> lock() const;
+
+

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

+

Throws: nothing.

+
+

reset

+
void reset();
+
+

Effects: Equivalent to weak_ptr().swap(*this).

+

swap

void swap(weak_ptr & b);
@@ -198,13 +203,6 @@ template<class Y> weak_ptr & operator=(shared_ptr<Y> const &

Notes: Matches the interface of std::swap. Provided as an aid to generic programming.

-

get_shared_ptr

-
template<class T>
-  shared_ptr<T> get_shared_ptr(weak_ptr<T> & const r)
-
-

Returns: r.expired()? shared_ptr<T>(): shared_ptr<T>(r).

-

Throws: nothing.

-

Frequently Asked Questions

Q. Can an object create a weak_ptr to itself in its constructor?