Add add_ref parameter to intrusive_ptr::reset, add tests for reset.

This commit is contained in:
Peter Dimov
2013-12-26 18:47:05 +02:00
parent 4e46cb0609
commit 4de3f36839
3 changed files with 221 additions and 10 deletions

View File

@@ -146,6 +146,11 @@ public:
this_type( rhs ).swap( *this );
}
void reset( T * rhs, bool add_ref )
{
this_type( rhs, add_ref ).swap( *this );
}
T * get() const BOOST_NOEXCEPT
{
return px;

View File

@@ -67,6 +67,7 @@
void <a href="#reset" >reset</a>();
void <a href="#reset" >reset</a>(T * r);
void <a href="#reset" >reset</a>(T * r, bool add_ref);
T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
@@ -161,6 +162,10 @@ intrusive_ptr &amp; operator=(T * r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>void reset(T * r, bool add_ref);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r, add_ref).swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<blockquote>
@@ -307,9 +312,7 @@ intrusive_ptr &amp; operator=(T * r);</pre>
</BLOCKQUOTE>
<hr>
<p>
$Date$</p>
<p>
<small>Copyright <20> 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version
<small>Copyright <20> 2003-2005, 2013 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>

View File

@@ -51,14 +51,18 @@ protected:
base(): use_count_(0)
{
++instances;
}
virtual ~base()
{
--instances;
}
public:
static long instances;
long use_count() const
{
return use_count_;
@@ -91,6 +95,8 @@ public:
#endif
};
long base::instances = 0;
} // namespace N
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
@@ -161,19 +167,27 @@ void pointer_constructor()
BOOST_TEST(px.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST(p->use_count() == 0);
BOOST_TEST( N::base::instances == 1 );
boost::intrusive_ptr<X> px(p);
BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST(p->use_count() == 0);
BOOST_TEST( N::base::instances == 1 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref;
#endif
@@ -184,6 +198,8 @@ void pointer_constructor()
BOOST_TEST(px.get() == p);
BOOST_TEST(px->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
}
void copy_constructor()
@@ -224,17 +240,27 @@ void copy_constructor()
BOOST_TEST(px.get() == py.get());
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px2.get() == px.get());
BOOST_TEST( px2.get() == px.get() );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<Y> py(new Y);
boost::intrusive_ptr<X> px(py);
BOOST_TEST(px.get() == py.get());
BOOST_TEST( px.get() == py.get() );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
}
void test()
@@ -251,15 +277,23 @@ namespace n_destructor
void test()
{
boost::intrusive_ptr<X> px(new X);
BOOST_TEST(px->use_count() == 1);
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px->use_count() == 2);
boost::intrusive_ptr<X> px(new X);
BOOST_TEST(px->use_count() == 1);
BOOST_TEST( N::base::instances == 1 );
{
boost::intrusive_ptr<X> px2(px);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST(px->use_count() == 1);
}
BOOST_TEST(px->use_count() == 1);
BOOST_TEST( N::base::instances == 0 );
}
} // namespace n_destructor
@@ -288,6 +322,174 @@ void test()
} // namespace n_assignment
namespace n_reset
{
void test()
{
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset();
BOOST_TEST( px.get() == 0 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
px.reset( p );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
px.reset();
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0 );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0, false );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( N::base::instances == 1 );
px.reset( 0, true );
BOOST_TEST( px.get() == 0 );
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset( p, true );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 1 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref;
#endif
intrusive_ptr_add_ref( p );
BOOST_TEST( p->use_count() == 1 );
boost::intrusive_ptr<X> px;
BOOST_TEST( px.get() == 0 );
px.reset( p, false );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p, true );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
BOOST_TEST( px.get() != 0 );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
X * p = new X;
BOOST_TEST( p->use_count() == 0 );
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
using boost::intrusive_ptr_add_ref;
#endif
intrusive_ptr_add_ref( p );
BOOST_TEST( p->use_count() == 1 );
BOOST_TEST( N::base::instances == 2 );
px.reset( p, false );
BOOST_TEST( px.get() == p );
BOOST_TEST( px->use_count() == 1 );
BOOST_TEST( N::base::instances == 1 );
}
BOOST_TEST( N::base::instances == 0 );
}
} // namespace n_reset
namespace n_access
{
@@ -572,6 +774,7 @@ int main()
n_constructors::test();
n_destructor::test();
n_assignment::test();
n_reset::test();
n_access::test();
n_swap::test();
n_comparison::test();