1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
//
// shared_from_raw_test5.cpp - was esft_constructor_test.cpp
//
// A test for calling shared_from_raw from constructors
// (that is, prior to the object's ownership being passed to
// an external shared_ptr).
//
// Copyright (c) 2008 Frank Mori Hess
// Copyright (c) 2008 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 <boost/smart_ptr/enable_shared_from_raw.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <memory>
class X: public boost::enable_shared_from_raw
{
private:
int destroyed_;
int deleted_;
int expected_;
private:
X( X const& );
X& operator=( X const& );
public:
static int instances;
public:
explicit X( int expected, boost::shared_ptr<X> *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
{
++instances;
if( early_px ) *early_px = shared_from_raw(this);
}
~X()
{
BOOST_TEST( deleted_ == expected_ );
BOOST_TEST( destroyed_ == 0 );
++destroyed_;
--instances;
}
typedef void (*deleter_type)( X* );
static void deleter( X * px )
{
++px->deleted_;
}
static void deleter2( X * px )
{
++px->deleted_;
delete px;
}
};
int X::instances = 0;
template<typename T, typename U>
bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
{
return !(a < b) && !(b < a);
}
struct Y: public boost::enable_shared_from_raw
{};
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X* x = new X( 1, &early_px );
BOOST_TEST( early_px.use_count() > 0 );
BOOST_TEST( boost::get_deleter<X::deleter_type>(early_px) == 0 );
BOOST_TEST( early_px.get() == x );
boost::shared_ptr<X> px( x, &X::deleter2 );
BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
BOOST_TEST(are_shared_owners(early_px, px));
px.reset();
BOOST_TEST( early_px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
X::deleter_type *pd = boost::get_deleter<X::deleter_type>(early_px);
BOOST_TEST(pd && *pd == &X::deleter2 );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X* x = new X( 1, &early_px );
boost::weak_ptr<X> early_weak_px = early_px;
early_px.reset();
BOOST_TEST( !early_weak_px.expired() );
boost::shared_ptr<X> px( x, &X::deleter2 );
BOOST_TEST( px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
BOOST_TEST(are_shared_owners(early_weak_px.lock(), px));
px.reset();
BOOST_TEST( early_weak_px.expired() );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X x( 2, &early_px );
BOOST_TEST( early_px.use_count() > 0 );
boost::shared_ptr<X> px( &x, &X::deleter );
BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
early_px.reset();
BOOST_TEST( px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
px.reset();
// test reinitialization after all shared_ptr have expired
early_px = shared_from_raw(&x);
px.reset( &x, &X::deleter );
BOOST_TEST(are_shared_owners(early_px, px));
early_px.reset();
}
BOOST_TEST( X::instances == 0 );
{
boost::weak_ptr<X> early_weak_px;
{
boost::shared_ptr<X> early_px;
X x( 0, &early_px );
early_weak_px = early_px;
early_px.reset();
BOOST_TEST( !early_weak_px.expired() );
BOOST_TEST( X::instances == 1 );
}
BOOST_TEST( early_weak_px.expired() );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<Y> px(new Y());
Y y(*px);
px.reset();
try
{
shared_from_raw(&y);
}
catch( const boost::bad_weak_ptr & )
{
BOOST_ERROR("y threw bad_weak_ptr");
}
}
return boost::report_errors();
}
|