1 /*
2  *             Copyright Andrey Semashev 2013.
3  * Distributed under the Boost Software License, Version 1.0.
4  *    (See accompanying file LICENSE_1_0.txt or copy at
5  *          http://www.boost.org/LICENSE_1_0.txt)
6  */
7 /*!
8  * \file   intrusive_ref_counter_test.cpp
9  * \author Andrey Semashev
10  * \date   31.08.2013
11  *
12  * This file contains tests for the \c intrusive_ref_counter base class.
13  */
14 
15 #include <boost/config.hpp>
16 
17 #if defined(BOOST_MSVC)
18 
19 #pragma warning(disable: 4786)  // identifier truncated in debug info
20 #pragma warning(disable: 4710)  // function not inlined
21 #pragma warning(disable: 4711)  // function selected for automatic inline expansion
22 #pragma warning(disable: 4514)  // unreferenced inline removed
23 #pragma warning(disable: 4355)  // 'this' : used in base member initializer list
24 #pragma warning(disable: 4511)  // copy constructor could not be generated
25 #pragma warning(disable: 4512)  // assignment operator could not be generated
26 
27 #if (BOOST_MSVC >= 1310)
28 #pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
29 #endif
30 
31 #endif
32 
33 #include <cstddef>
34 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
35 #include <boost/intrusive_ptr.hpp>
36 #include <boost/detail/lightweight_test.hpp>
37 
38 namespace N1 {
39 
40 class my_class :
41     public boost::intrusive_ref_counter< my_class >
42 {
43 public:
44     static unsigned int destructor_count;
45 
~my_class()46     ~my_class()
47     {
48         ++destructor_count;
49     }
50 };
51 
52 unsigned int my_class::destructor_count = 0;
53 
54 } // namespace N1
55 
56 namespace N2 {
57 
58 class my_class :
59     public boost::intrusive_ref_counter< my_class, boost::thread_unsafe_counter >
60 {
61 public:
62     static unsigned int destructor_count;
63 
~my_class()64     ~my_class()
65     {
66         ++destructor_count;
67     }
68 };
69 
70 unsigned int my_class::destructor_count = 0;
71 
72 } // namespace N2
73 
74 namespace N3 {
75 
76 struct root :
77     public boost::intrusive_ref_counter< root >
78 {
~rootN3::root79     virtual ~root() {}
80 };
81 
82 } // namespace N3
83 
84 namespace N4 {
85 
86 struct X :
87     public virtual N3::root
88 {
89 };
90 
91 } // namespace N4
92 
93 namespace N5 {
94 
95 struct Y :
96     public virtual N3::root
97 {
98 };
99 
100 } // namespace N5
101 
102 namespace N6 {
103 
104 struct Z :
105     public N4::X,
106     public N5::Y
107 {
108     static unsigned int destructor_count;
109 
~ZN6::Z110     ~Z()
111     {
112         ++destructor_count;
113     }
114 };
115 
116 unsigned int Z::destructor_count = 0;
117 
118 } // namespace N6
119 
120 
main()121 int main()
122 {
123     // The test check that ADL works
124     {
125         boost::intrusive_ptr< N1::my_class > p = new N1::my_class();
126         p = NULL;
127         BOOST_TEST(N1::my_class::destructor_count == 1);
128     }
129     {
130         boost::intrusive_ptr< N2::my_class > p = new N2::my_class();
131         p = NULL;
132         BOOST_TEST(N2::my_class::destructor_count == 1);
133     }
134     {
135         N1::my_class* p = new N1::my_class();
136         intrusive_ptr_add_ref(p);
137         intrusive_ptr_release(p);
138         BOOST_TEST(N1::my_class::destructor_count == 2);
139     }
140 
141     // The test checks that destroying through the base class works
142     {
143         boost::intrusive_ptr< N6::Z > p1 = new N6::Z();
144         BOOST_TEST(p1->use_count() == 1);
145         BOOST_TEST(N6::Z::destructor_count == 0);
146         boost::intrusive_ptr< N3::root > p2 = p1;
147         BOOST_TEST(p1->use_count() == 2);
148         BOOST_TEST(N6::Z::destructor_count == 0);
149         p1 = NULL;
150         BOOST_TEST(N6::Z::destructor_count == 0);
151         p2 = NULL;
152         BOOST_TEST(N6::Z::destructor_count == 1);
153     }
154 
155     return boost::report_errors();
156 }
157