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 ); this_type( rhs ).swap( *this );
} }
void reset( T * rhs, bool add_ref )
{
this_type( rhs, add_ref ).swap( *this );
}
T * get() const BOOST_NOEXCEPT T * get() const BOOST_NOEXCEPT
{ {
return px; return px;

View File

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

View File

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