From 6c5d29672248ba130b215358f074a950c2750713 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 13 Feb 2002 13:16:15 +0000 Subject: [PATCH] Modified weak_ptr to reflect list comments. [SVN r12793] --- include/boost/detail/shared_count.hpp | 12 ++--- include/boost/weak_ptr.hpp | 60 ++++++++--------------- shared_ptr_test.cpp | 68 +++++++++++++++++---------- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index ad08624..120fd47 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -31,19 +31,19 @@ namespace boost { -namespace detail -{ - -class bad_weak_to_shared_cast: public std::exception +class use_count_is_zero: public std::exception { public: virtual char const * what() const throw() { - return "bad_weak_to_shared_cast"; + return "use_count_is_zero"; } }; +namespace detail +{ + class counted_base { public: @@ -75,7 +75,7 @@ public: void add_ref() { lightweight_mutex::scoped_lock lock(mtx_); - if(use_count_ == 0) throw bad_weak_to_shared_cast(); + if(use_count_ == 0) throw use_count_is_zero(); ++use_count_; ++weak_count_; } diff --git a/include/boost/weak_ptr.hpp b/include/boost/weak_ptr.hpp index 624cded..9e9f1a2 100644 --- a/include/boost/weak_ptr.hpp +++ b/include/boost/weak_ptr.hpp @@ -30,7 +30,6 @@ private: // Borland 5.5.1 specific workarounds typedef weak_ptr this_type; - typedef shared_ptr shared_type; public: @@ -96,53 +95,16 @@ public: this_type().swap(*this); } - shared_type get() const // never throws + T * get() const // never throws; unsafe in multithreaded programs! { - // optimization: avoid throw overhead - if(use_count() == 0) - { - return shared_type(); - } - - try - { - return shared_type(*this); - } - catch(boost::detail::bad_weak_to_shared_cast const &) - { - return shared_type(); - } + return use_count() == 0? 0: px; } - // operator* has been removed; it's unsafe. - - // operator-> retained for convenience, since it's safe - // in its current form. - - shared_type operator-> () const // may throw - { - return shared_type(*this); - } - long use_count() const // never throws { return pn.use_count(); } - // implicit conversion to "bool" - - typedef long (this_type::*bool_type)() const; - - operator bool_type() const // never throws - { - return px == 0 || use_count() == 0? 0: &this_type::use_count; - } - - bool operator! () const // never throws - { - return px == 0 || use_count() == 0; - } - void swap(this_type & other) // never throws { std::swap(px, other.px); @@ -202,6 +164,24 @@ template void swap(weak_ptr & a, weak_ptr & b) a.swap(b); } +template shared_ptr make_shared(weak_ptr const & r) // never throws +{ + // optimization: avoid throw overhead + if(r.use_count() == 0) + { + return shared_ptr(); + } + + try + { + return shared_ptr(r); + } + catch(use_count_is_zero const &) + { + return shared_ptr(); + } +} + template weak_ptr shared_static_cast(weak_ptr const & r) { return weak_ptr(r, detail::static_cast_tag()); diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 749d8ee..5039e65 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -104,7 +104,8 @@ template void test_is_X(boost::shared_ptr const & p) template void test_is_X(boost::weak_ptr const & p) { - BOOST_TEST(p->id() == 1); + BOOST_TEST(p.get() != 0); + BOOST_TEST(p.get()->id() == 1); } template void test_is_Y(boost::shared_ptr const & p) @@ -115,7 +116,8 @@ template void test_is_Y(boost::shared_ptr const & p) template void test_is_Y(boost::weak_ptr const & p) { - BOOST_TEST(p->id() == 2); + BOOST_TEST(p.get() != 0); + BOOST_TEST(p.get()->id() == 2); } template void test_eq(T const & a, T const & b) @@ -152,24 +154,12 @@ template void test_is_zero(boost::shared_ptr const & p) BOOST_TEST(p.get() == 0); } -template void test_is_zero(boost::weak_ptr const & p) -{ - BOOST_TEST(!p); - test_is_zero(p.get()); -} - template void test_is_nonzero(boost::shared_ptr const & p) { BOOST_TEST(p); BOOST_TEST(p.get() != 0); } -template void test_is_nonzero(boost::weak_ptr const & p) -{ - BOOST_TEST(p); - test_is_nonzero(p.get()); -} - int test_main(int, char * []) { using namespace boost; @@ -228,35 +218,66 @@ int test_main(int, char * []) weak_ptr wp1; BOOST_TEST(wp1.use_count() == 0); - test_is_zero(wp1); + BOOST_TEST(wp1.get() == 0); + + try + { + shared_ptr sp1(wp1); + BOOST_ERROR("shared_ptr sp1(wp1) failed to throw"); + } + catch(boost::use_count_is_zero const &) + { + } + + test_is_zero(boost::make_shared(wp1)); weak_ptr wp2 = shared_static_cast(p5); BOOST_TEST(wp2.use_count() == 1); - test_is_nonzero(wp2); + BOOST_TEST(wp2.get() != 0); test_is_Y(wp2); test_ne(wp1, wp2); + // Scoped to not affect the subsequent use_count() tests. + { + shared_ptr sp2(wp2); + test_is_nonzero(boost::make_shared(wp2)); + } + weak_ptr wp3 = shared_dynamic_cast(wp2); BOOST_TEST(wp3.use_count() == 1); - test_is_nonzero(wp3); + BOOST_TEST(wp3.get() != 0); test_eq2(wp2, wp3); weak_ptr wp4(wp3); - test_is_nonzero(wp4); + BOOST_TEST(wp4.use_count() == 1); + BOOST_TEST(wp4.get() != 0); test_eq(wp2, wp4); wp1 = p2; - test_is_zero(wp1); + BOOST_TEST(wp1.get() == 0); + + // Note the following test. Construction succeeds, + // but make_shared() returns a null shared_ptr with + // use_count() == 2. + + shared_ptr sp1(wp1); + test_is_zero(boost::make_shared(wp1)); + + BOOST_TEST(p2.use_count() == 2); + BOOST_TEST(sp1.use_count() == 2); + BOOST_TEST(wp1.use_count() == 2); + + // wp1 = p4; wp1 = wp3; wp1 = wp2; BOOST_TEST(wp1.use_count() == 1); - test_is_nonzero(wp1); + BOOST_TEST(wp1.get() != 0); test_eq(wp1, wp2); weak_ptr wp5; @@ -265,16 +286,15 @@ int test_main(int, char * []) bool b2 = wp5 < wp1; p5.reset(); - test_is_zero(wp5); BOOST_TEST(wp1.use_count() == 0); - test_is_zero(wp1); + BOOST_TEST(wp1.get() == 0); BOOST_TEST(wp2.use_count() == 0); - test_is_zero(wp2); + BOOST_TEST(wp2.get() == 0); BOOST_TEST(wp3.use_count() == 0); - test_is_zero(wp3); + BOOST_TEST(wp3.get() == 0); // Test operator< stability for std::set< weak_ptr<> > // Thanks to Joe Gottman for pointing this out