Initialize boost git in 2.0_beta.
[external/boost.git] / libs / smart_ptr / test / intrusive_ptr_test.cpp
1 #include <boost/config.hpp>
2
3 #if defined(BOOST_MSVC)
4
5 #pragma warning(disable: 4786)  // identifier truncated in debug info
6 #pragma warning(disable: 4710)  // function not inlined
7 #pragma warning(disable: 4711)  // function selected for automatic inline expansion
8 #pragma warning(disable: 4514)  // unreferenced inline removed
9 #pragma warning(disable: 4355)  // 'this' : used in base member initializer list
10 #pragma warning(disable: 4511)  // copy constructor could not be generated
11 #pragma warning(disable: 4512)  // assignment operator could not be generated
12
13 #if (BOOST_MSVC >= 1310)
14 #pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
15 #endif
16
17 #endif
18
19 //
20 //  intrusive_ptr_test.cpp
21 //
22 //  Copyright (c) 2002-2005 Peter Dimov
23 //
24 // Distributed under the Boost Software License, Version 1.0. (See
25 // accompanying file LICENSE_1_0.txt or copy at
26 // http://www.boost.org/LICENSE_1_0.txt)
27 //
28
29 #include <boost/detail/lightweight_test.hpp>
30 #include <boost/intrusive_ptr.hpp>
31 #include <boost/detail/atomic_count.hpp>
32 #include <boost/config.hpp>
33 #include <algorithm>
34 #include <functional>
35
36 //
37
38 namespace N
39 {
40
41 class base
42 {
43 private:
44
45     boost::detail::atomic_count use_count_;
46
47     base(base const &);
48     base & operator=(base const &);
49
50 protected:
51
52     base(): use_count_(0)
53     {
54     }
55
56     virtual ~base()
57     {
58     }
59
60 public:
61
62     long use_count() const
63     {
64         return use_count_;
65     }
66
67 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
68
69     inline friend void intrusive_ptr_add_ref(base * p)
70     {
71         ++p->use_count_;
72     }
73
74     inline friend void intrusive_ptr_release(base * p)
75     {
76         if(--p->use_count_ == 0) delete p;
77     }
78
79 #else
80
81     void add_ref()
82     {
83         ++use_count_;
84     }
85
86     void release()
87     {
88         if(--use_count_ == 0) delete this;
89     }
90
91 #endif
92 };
93
94 } // namespace N
95
96 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
97
98 namespace boost
99 {
100
101 inline void intrusive_ptr_add_ref(N::base * p)
102 {
103     p->add_ref();
104 }
105
106 inline void intrusive_ptr_release(N::base * p)
107 {
108     p->release();
109 }
110
111 } // namespace boost
112
113 #endif
114
115 //
116
117 struct X: public virtual N::base
118 {
119 };
120
121 struct Y: public X
122 {
123 };
124
125 //
126
127 namespace n_element_type
128 {
129
130 void f(X &)
131 {
132 }
133
134 void test()
135 {
136     typedef boost::intrusive_ptr<X>::element_type T;
137     T t;
138     f(t);
139 }
140
141 } // namespace n_element_type
142
143 namespace n_constructors
144 {
145
146 void default_constructor()
147 {
148     boost::intrusive_ptr<X> px;
149     BOOST_TEST(px.get() == 0);
150 }
151
152 void pointer_constructor()
153 {
154     {
155         boost::intrusive_ptr<X> px(0);
156         BOOST_TEST(px.get() == 0);
157     }
158
159     {
160         boost::intrusive_ptr<X> px(0, false);
161         BOOST_TEST(px.get() == 0);
162     }
163
164     {
165         X * p = new X;
166         BOOST_TEST(p->use_count() == 0);
167
168         boost::intrusive_ptr<X> px(p);
169         BOOST_TEST(px.get() == p);
170         BOOST_TEST(px->use_count() == 1);
171     }
172
173     {
174         X * p = new X;
175         BOOST_TEST(p->use_count() == 0);
176
177 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
178         using boost::intrusive_ptr_add_ref;
179 #endif
180         intrusive_ptr_add_ref(p);
181         BOOST_TEST(p->use_count() == 1);
182
183         boost::intrusive_ptr<X> px(p, false);
184         BOOST_TEST(px.get() == p);
185         BOOST_TEST(px->use_count() == 1);
186     }
187 }
188
189 void copy_constructor()
190 {
191     {
192         boost::intrusive_ptr<X> px;
193         boost::intrusive_ptr<X> px2(px);
194         BOOST_TEST(px2.get() == px.get());
195     }
196
197     {
198         boost::intrusive_ptr<Y> py;
199         boost::intrusive_ptr<X> px(py);
200         BOOST_TEST(px.get() == py.get());
201     }
202
203     {
204         boost::intrusive_ptr<X> px(0);
205         boost::intrusive_ptr<X> px2(px);
206         BOOST_TEST(px2.get() == px.get());
207     }
208
209     {
210         boost::intrusive_ptr<Y> py(0);
211         boost::intrusive_ptr<X> px(py);
212         BOOST_TEST(px.get() == py.get());
213     }
214
215     {
216         boost::intrusive_ptr<X> px(0, false);
217         boost::intrusive_ptr<X> px2(px);
218         BOOST_TEST(px2.get() == px.get());
219     }
220
221     {
222         boost::intrusive_ptr<Y> py(0, false);
223         boost::intrusive_ptr<X> px(py);
224         BOOST_TEST(px.get() == py.get());
225     }
226
227     {
228         boost::intrusive_ptr<X> px(new X);
229         boost::intrusive_ptr<X> px2(px);
230         BOOST_TEST(px2.get() == px.get());
231     }
232
233     {
234         boost::intrusive_ptr<Y> py(new Y);
235         boost::intrusive_ptr<X> px(py);
236         BOOST_TEST(px.get() == py.get());
237     }
238 }
239
240 void test()
241 {
242     default_constructor();
243     pointer_constructor();
244     copy_constructor();
245 }
246
247 } // namespace n_constructors
248
249 namespace n_destructor
250 {
251
252 void test()
253 {
254     boost::intrusive_ptr<X> px(new X);
255     BOOST_TEST(px->use_count() == 1);
256
257     {
258         boost::intrusive_ptr<X> px2(px);
259         BOOST_TEST(px->use_count() == 2);
260     }
261
262     BOOST_TEST(px->use_count() == 1);
263 }
264
265 } // namespace n_destructor
266
267 namespace n_assignment
268 {
269
270 void copy_assignment()
271 {
272 }
273
274 void conversion_assignment()
275 {
276 }
277
278 void pointer_assignment()
279 {
280 }
281
282 void test()
283 {
284     copy_assignment();
285     conversion_assignment();
286     pointer_assignment();
287 }
288
289 } // namespace n_assignment
290
291 namespace n_access
292 {
293
294 void test()
295 {
296     {
297         boost::intrusive_ptr<X> px;
298         BOOST_TEST(px? false: true);
299         BOOST_TEST(!px);
300
301 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
302         using boost::get_pointer;
303 #endif
304
305         BOOST_TEST(get_pointer(px) == px.get());
306     }
307
308     {
309         boost::intrusive_ptr<X> px(0);
310         BOOST_TEST(px? false: true);
311         BOOST_TEST(!px);
312
313 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
314         using boost::get_pointer;
315 #endif
316
317         BOOST_TEST(get_pointer(px) == px.get());
318     }
319
320     {
321         boost::intrusive_ptr<X> px(new X);
322         BOOST_TEST(px? true: false);
323         BOOST_TEST(!!px);
324         BOOST_TEST(&*px == px.get());
325         BOOST_TEST(px.operator ->() == px.get());
326
327 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
328         using boost::get_pointer;
329 #endif
330
331         BOOST_TEST(get_pointer(px) == px.get());
332     }
333 }
334
335 } // namespace n_access
336
337 namespace n_swap
338 {
339
340 void test()
341 {
342     {
343         boost::intrusive_ptr<X> px;
344         boost::intrusive_ptr<X> px2;
345
346         px.swap(px2);
347
348         BOOST_TEST(px.get() == 0);
349         BOOST_TEST(px2.get() == 0);
350
351         using std::swap;
352         swap(px, px2);
353
354         BOOST_TEST(px.get() == 0);
355         BOOST_TEST(px2.get() == 0);
356     }
357
358     {
359         X * p = new X;
360         boost::intrusive_ptr<X> px;
361         boost::intrusive_ptr<X> px2(p);
362         boost::intrusive_ptr<X> px3(px2);
363
364         px.swap(px2);
365
366         BOOST_TEST(px.get() == p);
367         BOOST_TEST(px->use_count() == 2);
368         BOOST_TEST(px2.get() == 0);
369         BOOST_TEST(px3.get() == p);
370         BOOST_TEST(px3->use_count() == 2);
371
372         using std::swap;
373         swap(px, px2);
374
375         BOOST_TEST(px.get() == 0);
376         BOOST_TEST(px2.get() == p);
377         BOOST_TEST(px2->use_count() == 2);
378         BOOST_TEST(px3.get() == p);
379         BOOST_TEST(px3->use_count() == 2);
380     }
381
382     {
383         X * p1 = new X;
384         X * p2 = new X;
385         boost::intrusive_ptr<X> px(p1);
386         boost::intrusive_ptr<X> px2(p2);
387         boost::intrusive_ptr<X> px3(px2);
388
389         px.swap(px2);
390
391         BOOST_TEST(px.get() == p2);
392         BOOST_TEST(px->use_count() == 2);
393         BOOST_TEST(px2.get() == p1);
394         BOOST_TEST(px2->use_count() == 1);
395         BOOST_TEST(px3.get() == p2);
396         BOOST_TEST(px3->use_count() == 2);
397
398         using std::swap;
399         swap(px, px2);
400
401         BOOST_TEST(px.get() == p1);
402         BOOST_TEST(px->use_count() == 1);
403         BOOST_TEST(px2.get() == p2);
404         BOOST_TEST(px2->use_count() == 2);
405         BOOST_TEST(px3.get() == p2);
406         BOOST_TEST(px3->use_count() == 2);
407     }
408 }
409
410 } // namespace n_swap
411
412 namespace n_comparison
413 {
414
415 template<class T, class U> void test2(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<U> const & q)
416 {
417     BOOST_TEST((p == q) == (p.get() == q.get()));
418     BOOST_TEST((p != q) == (p.get() != q.get()));
419 }
420
421 template<class T> void test3(boost::intrusive_ptr<T> const & p, boost::intrusive_ptr<T> const & q)
422 {
423     BOOST_TEST((p == q) == (p.get() == q.get()));
424     BOOST_TEST((p.get() == q) == (p.get() == q.get()));
425     BOOST_TEST((p == q.get()) == (p.get() == q.get()));
426     BOOST_TEST((p != q) == (p.get() != q.get()));
427     BOOST_TEST((p.get() != q) == (p.get() != q.get()));
428     BOOST_TEST((p != q.get()) == (p.get() != q.get()));
429
430     // 'less' moved here as a g++ 2.9x parse error workaround
431     std::less<T*> less;
432     BOOST_TEST((p < q) == less(p.get(), q.get()));
433 }
434
435 void test()
436 {
437     {
438         boost::intrusive_ptr<X> px;
439         test3(px, px);
440
441         boost::intrusive_ptr<X> px2;
442         test3(px, px2);
443
444         boost::intrusive_ptr<X> px3(px);
445         test3(px3, px3);
446         test3(px, px3);
447     }
448
449     {
450         boost::intrusive_ptr<X> px;
451
452         boost::intrusive_ptr<X> px2(new X);
453         test3(px, px2);
454         test3(px2, px2);
455
456         boost::intrusive_ptr<X> px3(new X);
457         test3(px2, px3);
458
459         boost::intrusive_ptr<X> px4(px2);
460         test3(px2, px4);
461         test3(px4, px4);
462     }
463
464     {
465         boost::intrusive_ptr<X> px(new X);
466
467         boost::intrusive_ptr<Y> py(new Y);
468         test2(px, py);
469
470         boost::intrusive_ptr<X> px2(py);
471         test2(px2, py);
472         test3(px, px2);
473         test3(px2, px2);
474     }
475 }
476
477 } // namespace n_comparison
478
479 namespace n_static_cast
480 {
481
482 void test()
483 {
484 }
485
486 } // namespace n_static_cast
487
488 namespace n_dynamic_cast
489 {
490
491 void test()
492 {
493 }
494
495 } // namespace n_dynamic_cast
496
497 namespace n_transitive
498 {
499
500 struct X: public N::base
501 {
502     boost::intrusive_ptr<X> next;
503 };
504
505 void test()
506 {
507     boost::intrusive_ptr<X> p(new X);
508     p->next = boost::intrusive_ptr<X>(new X);
509     BOOST_TEST(!p->next->next);
510     p = p->next;
511     BOOST_TEST(!p->next);
512 }
513
514 } // namespace n_transitive
515
516 namespace n_report_1
517 {
518
519 class foo: public N::base
520
521 public: 
522
523     foo(): m_self(this)
524     {
525     } 
526
527     void suicide()
528     {
529         m_self = 0;
530     }
531
532 private:
533
534     boost::intrusive_ptr<foo> m_self;
535 }; 
536
537 void test()
538 {
539     foo * foo_ptr = new foo;
540     foo_ptr->suicide();
541
542
543 } // namespace n_report_1
544
545 int main()
546 {
547     n_element_type::test();
548     n_constructors::test();
549     n_destructor::test();
550     n_assignment::test();
551     n_access::test();
552     n_swap::test();
553     n_comparison::test();
554     n_static_cast::test();
555     n_dynamic_cast::test();
556
557     n_transitive::test();
558     n_report_1::test();
559
560     return boost::report_errors();
561 }