|
Boost : |
Subject: [boost] enable_shared_from_this2
From: Berserker (berserker_r_at_[hidden])
Date: 2009-10-26 07:07:38
After experiencing some troubles with boost::python and
enable_shared_from_this (as already reported in the past by someone to
Peter Dimov), I started looking at the new (not documented) class
enable_shared_from_this2.
I made two changes in init_weak_once and now it seems to support
shared_from_this in constructors and shared pointers "reinitialization".
The original code (from boost 1.40):
void init_weak_once() const
{
if( weak_this_._empty() )
{
shared_this_.reset(static_cast< T* >( 0 ),
detail::esft2_deleter_wrapper());
weak_this_ = shared_this_;
}
}
The "patched" code:
void init_weak_once() const
{
// Reinitialization support
if( weak_this_.expired() )
{
// shared_from_this in costructors support
shared_this_.reset(static_cast
<T*>(const_cast<enable_shared_from_this2>(this)),
detail::esft2_deleter_wrapper());
weak_this_ = shared_this_;
}
}
I know that the static_cast/const_cast is "problematic" on VC6 (and
maybe other compilers) but it could be solved using an offset from
enable_shared_from_this2 * to T *.
I've attached a testcase that shows the problems with the current
enable_shared_from_this2 implementation (with the proposed patch it works).
Any feedback about this?
struct null_deleter
{
template <typename T>
inline void operator()(T *p) const { }
};
class EnableThisPtrTester : public boost::enable_shared_from_this2<EnableThisPtrTester>
{
public:
EnableThisPtrTester()
{
}
EnableThisPtrTester(shared_ptr<EnableThisPtrTester> &ptr)
{
ptr = shared_from_this();
BOOST_CHECK(ptr);
}
};
BOOST_AUTO_TEST_CASE(test_enable_this_ptr)
{
{
shared_ptr<EnableThisPtrTester> ptr1;
shared_ptr<EnableThisPtrTester> ptr2(new EnableThisPtrTester(ptr1));
BOOST_CHECK(ptr1 == ptr2);
BOOST_CHECK(ptr1.use_count() == ptr2.use_count());
BOOST_CHECK(ptr1->shared_from_this() == ptr1);
BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count());
shared_ptr<EnableThisPtrTester> ptr3 = ptr2->shared_from_this();
BOOST_CHECK(ptr2 == ptr3);
BOOST_CHECK(ptr2.use_count() == ptr3.use_count());
BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count());
}
{
shared_ptr<EnableThisPtrTester> ptr1;
EnableThisPtrTester tester(ptr1);
shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this();
BOOST_CHECK(ptr1 == ptr2);
BOOST_CHECK(ptr1.use_count() == ptr2.use_count());
ptr1.reset();
ptr2.reset();
}
{
EnableThisPtrTester tester;
{
shared_ptr<EnableThisPtrTester> ptr1 = tester.shared_from_this();
shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this();
BOOST_CHECK(ptr1 == ptr2);
BOOST_CHECK(ptr1.use_count() == ptr2.use_count());
shared_ptr<EnableThisPtrTester> ptr3(&tester, null_deleter());
BOOST_CHECK(ptr1 == ptr3);
BOOST_CHECK(ptr1.use_count() == ptr3.use_count());
shared_ptr<EnableThisPtrTester> ptr4 = tester.shared_from_this();
BOOST_CHECK(ptr4 == ptr1);
BOOST_CHECK(ptr4 == ptr3);
BOOST_CHECK(ptr1.use_count() == ptr4.use_count());
BOOST_CHECK(ptr3.use_count() == ptr4.use_count());
}
BOOST_CHECK(tester.shared_from_this());
}
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk