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