diff --git a/include/boost/smart_ptr/enable_shared_from_raw.hpp b/include/boost/smart_ptr/enable_shared_from_raw.hpp index 1911c07..669a649 100644 --- a/include/boost/smart_ptr/enable_shared_from_raw.hpp +++ b/include/boost/smart_ptr/enable_shared_from_raw.hpp @@ -53,7 +53,7 @@ protected: private: - void init_weak_once() const + void init_if_expired() const { if( weak_this_.expired() ) { @@ -62,6 +62,15 @@ private: } } + void init_if_empty() const + { + if( weak_this_._empty() ) + { + shared_this_.reset( static_cast(0), detail::esft2_deleter_wrapper() ); + weak_this_ = shared_this_; + } + } + #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS public: #else @@ -74,7 +83,7 @@ private: shared_ptr shared_from_this() const { - init_weak_once(); + init_if_expired(); return shared_ptr( weak_this_ ); } @@ -83,6 +92,17 @@ private: return const_cast< enable_shared_from_raw const * >( this )->shared_from_this(); } + weak_ptr weak_from_this() const + { + init_if_empty(); + return weak_this_; + } + + weak_ptr weak_from_this() const volatile + { + return const_cast< enable_shared_from_raw const * >( this )->weak_from_this(); + } + // Note: invoked automatically by shared_ptr; do not call template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const { @@ -125,7 +145,7 @@ boost::weak_ptr weak_from_raw(T *p) { BOOST_ASSERT(p != 0); boost::weak_ptr result; - result._internal_aliasing_assign(p->enable_shared_from_raw::weak_this_, p); + result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p); return result; } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0b51eee..a848d4f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -171,6 +171,8 @@ import testing ; [ run weak_from_raw_test.cpp ] [ run weak_from_raw_test2.cpp ] + [ run weak_from_raw_test3.cpp ] + [ run weak_from_raw_test4.cpp ] [ compile sp_explicit_inst_test.cpp ] ; diff --git a/test/weak_from_raw_test.cpp b/test/weak_from_raw_test.cpp index ba95ecc..34d21eb 100644 --- a/test/weak_from_raw_test.cpp +++ b/test/weak_from_raw_test.cpp @@ -12,7 +12,6 @@ #include - #include @@ -23,7 +22,7 @@ void basic_weak_from_raw_test() { X *p(new X); boost::weak_ptr weak = boost::weak_from_raw(p); - BOOST_TEST(weak.expired()); + BOOST_TEST(!weak.expired()); boost::shared_ptr shared(p); weak = boost::weak_from_raw(p); BOOST_TEST(weak.expired() == false); diff --git a/test/weak_from_raw_test3.cpp b/test/weak_from_raw_test3.cpp new file mode 100644 index 0000000..ee73b4c --- /dev/null +++ b/test/weak_from_raw_test3.cpp @@ -0,0 +1,46 @@ +// +// weak_from_raw_test3.cpp +// +// Test that weak_from_raw and shared_from_raw +// return consistent values from a constructor +// +// Copyright (c) 2015 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include +#include + +class X: public boost::enable_shared_from_raw +{ +public: + + X() + { + boost::weak_ptr p1 = boost::weak_from_raw( this ); + BOOST_TEST( !p1.expired() ); + + boost::weak_ptr p2 = boost::weak_from_raw( this ); + BOOST_TEST( !p2.expired() ); + BOOST_TEST( !( p1 < p2 ) && !( p2 < p1 ) ); + + boost::weak_ptr p3 = boost::shared_from_raw( this ); + BOOST_TEST( !( p1 < p3 ) && !( p3 < p1 ) ); + + boost::weak_ptr p4 = boost::weak_from_raw( this ); + BOOST_TEST( !p4.expired() ); + BOOST_TEST( !( p3 < p4 ) && !( p4 < p3 ) ); + BOOST_TEST( !( p1 < p4 ) && !( p4 < p1 ) ); + } +}; + +int main() +{ + boost::shared_ptr< X > px( new X ); + return boost::report_errors(); +} diff --git a/test/weak_from_raw_test4.cpp b/test/weak_from_raw_test4.cpp new file mode 100644 index 0000000..646b84e --- /dev/null +++ b/test/weak_from_raw_test4.cpp @@ -0,0 +1,67 @@ +// +// weak_from_raw_test4.cpp +// +// As weak_from_raw_test2.cpp, but uses weak_from_this +// in the constructor +// +// Copyright (c) 2014, 2015 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include +#include +#include + +class X; + +static boost::weak_ptr< X > r_; + +void register_( boost::weak_ptr< X > const & r ) +{ + r_ = r; +} + +void check_( boost::weak_ptr< X > const & r ) +{ + BOOST_TEST( !( r < r_ ) && !( r_ < r ) ); +} + +void unregister_( boost::weak_ptr< X > const & r ) +{ + BOOST_TEST( !( r < r_ ) && !( r_ < r ) ); + r_.reset(); +} + +class X: public boost::enable_shared_from_raw +{ +public: + + X() + { + register_( boost::weak_from_raw( this ) ); + } + + ~X() + { + unregister_( boost::weak_from_raw( this ) ); + } + + void check() + { + check_( boost::weak_from_raw( this ) ); + } +}; + +int main() +{ + { + boost::shared_ptr< X > px( new X ); + px->check(); + } + + return boost::report_errors(); +}