diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index dd6ba2d..afdb42b 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -120,19 +120,28 @@ public: void release() // nothrow { long new_use_count; - long new_weak_count; + long new_weak_count = 0; { #ifdef BOOST_HAS_THREADS mutex_type::scoped_lock lock(mtx_); #endif new_use_count = --use_count_; - new_weak_count = --weak_count_; + + if(new_use_count != 0) + { + new_weak_count = --weak_count_; + } } if(new_use_count == 0) { dispose(); + +#ifdef BOOST_HAS_THREADS + mutex_type::scoped_lock lock(mtx_); +#endif + new_weak_count = --weak_count_; } if(new_weak_count == 0) diff --git a/shared_ptr_test.cpp b/shared_ptr_test.cpp index 56f6e46..3b0ec5e 100644 --- a/shared_ptr_test.cpp +++ b/shared_ptr_test.cpp @@ -196,6 +196,45 @@ template void test_is_nonzero(boost::shared_ptr const & p) BOOST_TEST(p.get() != 0); } +class foo +{ +public: + + void setWeak(boost::shared_ptr s) + { + w = s; + } + +private: + + boost::weak_ptr w; +}; + +class deleter +{ +public: + + deleter(): lock(0) + { + } + + ~deleter() + { + BOOST_TEST(lock == 0); + } + + void operator() (foo * p) + { + ++lock; + delete p; + --lock; + } + +private: + + int lock; +}; + int main() { using namespace boost; @@ -368,5 +407,12 @@ int main() BOOST_TEST(cnt == 0); + // Test case by Per Kristensen + { + boost::shared_ptr s(new foo, deleter()); + s->setWeak(s); + s.reset(); + } + return boost::report_errors(); }