1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #include <boost/interprocess/offset_ptr.hpp>
12 #include <boost/interprocess/detail/type_traits.hpp>
13 #include <boost/intrusive/pointer_traits.hpp>
14 #include <boost/static_assert.hpp>
15 #include <boost/core/lightweight_test.hpp>
16 
17 using namespace boost::interprocess;
18 
19 class Base
20 {};
21 
22 class Derived
23    : public Base
24 {};
25 
26 class VirtualDerived
27    : public virtual Base
28 {};
29 
test_types_and_conversions()30 void test_types_and_conversions()
31 {
32    typedef offset_ptr<int>                pint_t;
33    typedef offset_ptr<const int>          pcint_t;
34    typedef offset_ptr<volatile int>       pvint_t;
35    typedef offset_ptr<const volatile int> pcvint_t;
36 
37    BOOST_STATIC_ASSERT((ipcdetail::is_same<pint_t::element_type, int>::value));
38    BOOST_STATIC_ASSERT((ipcdetail::is_same<pcint_t::element_type, const int>::value));
39    BOOST_STATIC_ASSERT((ipcdetail::is_same<pvint_t::element_type, volatile int>::value));
40    BOOST_STATIC_ASSERT((ipcdetail::is_same<pcvint_t::element_type, const volatile int>::value));
41 
42    BOOST_STATIC_ASSERT((ipcdetail::is_same<pint_t::value_type,   int>::value));
43    BOOST_STATIC_ASSERT((ipcdetail::is_same<pcint_t::value_type,  int>::value));
44    BOOST_STATIC_ASSERT((ipcdetail::is_same<pvint_t::value_type,  int>::value));
45    BOOST_STATIC_ASSERT((ipcdetail::is_same<pcvint_t::value_type, int>::value));
46    int dummy_int = 9;
47 
48    {  pint_t pint(&dummy_int);
49       pcint_t  pcint(pint);
50       BOOST_TEST(pcint.get() == &dummy_int);
51    }
52    {  pint_t pint(&dummy_int);
53       pvint_t  pvint(pint);
54       BOOST_TEST(pvint.get() == &dummy_int);
55    }
56    {  pint_t pint(&dummy_int);
57       pcvint_t  pcvint(pint);
58       BOOST_TEST(pcvint.get() == &dummy_int);
59    }
60    {  pcint_t pcint(&dummy_int);
61       pcvint_t  pcvint(pcint);
62       BOOST_TEST(pcvint.get() == &dummy_int);
63    }
64    {  pvint_t pvint(&dummy_int);
65       pcvint_t  pcvint(pvint);
66       BOOST_TEST(pcvint.get() == &dummy_int);
67    }
68 
69    pint_t   pint(0);
70    pcint_t  pcint(0);
71    pvint_t  pvint(0);
72    pcvint_t pcvint(0);
73 
74    pint     = &dummy_int;
75    pcint    = &dummy_int;
76    pvint    = &dummy_int;
77    pcvint   = &dummy_int;
78 
79    {  pcint  = pint;
80       BOOST_TEST(pcint.get() == &dummy_int);
81    }
82    {  pvint  = pint;
83       BOOST_TEST(pvint.get() == &dummy_int);
84    }
85    {  pcvint = pint;
86       BOOST_TEST(pcvint.get() == &dummy_int);
87    }
88    {  pcvint = pcint;
89       BOOST_TEST(pcvint.get() == &dummy_int);
90    }
91    {  pcvint = pvint;
92       BOOST_TEST(pcvint.get() == &dummy_int);
93    }
94 
95    BOOST_TEST(pint);
96 
97    pint = 0;
98    BOOST_TEST(!pint);
99 
100    BOOST_TEST(pint == 0);
101 
102    BOOST_TEST(0 == pint);
103 
104    pint = &dummy_int;
105    BOOST_TEST(0 != pint);
106 
107    pcint = &dummy_int;
108 
109    BOOST_TEST( (pcint - pint) == 0);
110    BOOST_TEST( (pint - pcint) == 0);
111 }
112 
113 template<class BasePtr, class DerivedPtr>
test_base_derived_impl()114 void test_base_derived_impl()
115 {
116    typename DerivedPtr::element_type d;
117    DerivedPtr pderi(&d);
118 
119    BasePtr pbase(pderi);
120    pbase = pderi;
121    BOOST_TEST(pbase == pderi);
122    BOOST_TEST(!(pbase != pderi));
123    BOOST_TEST((pbase - pderi) == 0);
124    BOOST_TEST(!(pbase < pderi));
125    BOOST_TEST(!(pbase > pderi));
126    BOOST_TEST(pbase <= pderi);
127    BOOST_TEST((pbase >= pderi));
128 }
129 
test_base_derived()130 void test_base_derived()
131 {
132    typedef offset_ptr<Base>               pbase_t;
133    typedef offset_ptr<const Base>         pcbas_t;
134    typedef offset_ptr<Derived>            pderi_t;
135    typedef offset_ptr<VirtualDerived>     pvder_t;
136 
137    test_base_derived_impl<pbase_t, pderi_t>();
138    test_base_derived_impl<pbase_t, pvder_t>();
139    test_base_derived_impl<pcbas_t, pderi_t>();
140    test_base_derived_impl<pcbas_t, pvder_t>();
141 }
142 
test_arithmetic()143 void test_arithmetic()
144 {
145    typedef offset_ptr<int> pint_t;
146    const int NumValues = 5;
147    int values[NumValues];
148 
149    //Initialize p
150    pint_t p = values;
151    BOOST_TEST(p.get() == values);
152 
153    //Initialize p + NumValues
154    pint_t pe = &values[NumValues];
155    BOOST_TEST(pe != p);
156    BOOST_TEST(pe.get() == &values[NumValues]);
157 
158    //ptr - ptr
159    BOOST_TEST((pe - p) == NumValues);
160 
161    //ptr - integer
162    BOOST_TEST((pe - NumValues) == p);
163 
164    //ptr + integer
165    BOOST_TEST((p + NumValues) == pe);
166 
167    //integer + ptr
168    BOOST_TEST((NumValues + p) == pe);
169 
170    //indexing
171    BOOST_TEST(pint_t(&p[NumValues]) == pe);
172    BOOST_TEST(pint_t(&pe[-NumValues]) == p);
173 
174    //ptr -= integer
175    pint_t p0 = pe;
176    p0-= NumValues;
177    BOOST_TEST(p == p0);
178 
179    //ptr += integer
180    pint_t penew = p0;
181    penew += NumValues;
182    BOOST_TEST(penew == pe);
183 
184    //++ptr
185    penew = p0;
186    for(int j = 0; j != NumValues; ++j, ++penew);
187    BOOST_TEST(penew == pe);
188 
189    //--ptr
190    p0 = pe;
191    for(int j = 0; j != NumValues; ++j, --p0);
192    BOOST_TEST(p == p0);
193 
194    //ptr++
195    penew = p0;
196    for(int j = 0; j != NumValues; ++j){
197       pint_t p_new_copy = penew;
198       BOOST_TEST(p_new_copy == penew++);
199    }
200    //ptr--
201    p0 = pe;
202    for(int j = 0; j != NumValues; ++j){
203       pint_t p0_copy = p0;
204       BOOST_TEST(p0_copy == p0--);
205    }
206 }
207 
test_comparison()208 void test_comparison()
209 {
210    typedef offset_ptr<int> pint_t;
211    const int NumValues = 5;
212    int values[NumValues];
213 
214    //Initialize p
215    pint_t p = values;
216    BOOST_TEST(p.get() == values);
217 
218    //Initialize p + NumValues
219    pint_t pe = &values[NumValues];
220    BOOST_TEST(pe != p);
221 
222    BOOST_TEST(pe.get() == &values[NumValues]);
223 
224    //operators
225    BOOST_TEST(p != pe);
226    BOOST_TEST(p == p);
227    BOOST_TEST((p < pe));
228    BOOST_TEST((p <= pe));
229    BOOST_TEST((pe > p));
230    BOOST_TEST((pe >= p));
231 }
232 
test_pointer_traits()233 bool test_pointer_traits()
234 {
235    typedef offset_ptr<int> OInt;
236    typedef boost::intrusive::pointer_traits< OInt > PTOInt;
237    BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::element_type, int>::value));
238    BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::pointer, OInt >::value));
239    BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::difference_type, OInt::difference_type >::value));
240    BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::rebind_pointer<double>::type, offset_ptr<double> >::value));
241    int dummy;
242    OInt oi(&dummy);
243    if(boost::intrusive::pointer_traits<OInt>::pointer_to(dummy) != oi){
244       return false;
245    }
246    return true;
247 }
248 
249 struct node
250 {
251    offset_ptr<node> next;
252 };
253 
test_pointer_plus_bits()254 void test_pointer_plus_bits()
255 {
256    BOOST_STATIC_ASSERT((boost::intrusive::max_pointer_plus_bits< offset_ptr<void>, boost::move_detail::alignment_of<node>::value >::value >= 1U));
257    typedef boost::intrusive::pointer_plus_bits< offset_ptr<node>, 1u > ptr_plus_bits;
258 
259    node n, n2;
260    offset_ptr<node> pnode(&n);
261 
262    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) == &n);
263    BOOST_TEST(0 == ptr_plus_bits::get_bits(pnode));
264    ptr_plus_bits::set_bits(pnode, 1u);
265    BOOST_TEST(1 == ptr_plus_bits::get_bits(pnode));
266    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) == &n);
267 
268    ptr_plus_bits::set_pointer(pnode, &n2);
269    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) == &n2);
270    BOOST_TEST(1 == ptr_plus_bits::get_bits(pnode));
271    ptr_plus_bits::set_bits(pnode, 0u);
272    BOOST_TEST(0 == ptr_plus_bits::get_bits(pnode));
273    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) == &n2);
274 
275    ptr_plus_bits::set_pointer(pnode, offset_ptr<node>());
276    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) ==0);
277    BOOST_TEST(0 == ptr_plus_bits::get_bits(pnode));
278    ptr_plus_bits::set_bits(pnode, 1u);
279    BOOST_TEST(1 == ptr_plus_bits::get_bits(pnode));
280    BOOST_TEST(ptr_plus_bits::get_pointer(pnode) == 0);
281 }
282 
main()283 int main()
284 {
285    test_types_and_conversions();
286    test_base_derived();
287    test_arithmetic();
288    test_comparison();
289    test_pointer_traits();
290    test_pointer_plus_bits();
291    return ::boost::report_errors();
292 }
293