| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2007. 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) |
| // |
| // See http://www.boost.org/libs/interprocess for documentation. |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| #include <boost/interprocess/detail/config_begin.hpp> |
| |
| #include <boost/interprocess/detail/intersegment_ptr.hpp> |
| #include <boost/interprocess/detail/type_traits.hpp> |
| #include <boost/interprocess/mapped_region.hpp> //mapped_region |
| #include <boost/interprocess/anonymous_shared_memory.hpp> //anonymous_shared_memory |
| #include <boost/interprocess/detail/managed_multi_shared_memory.hpp> //managed_multi_shared_memory |
| #include <cstddef> //std::size_t |
| |
| |
| using namespace boost::interprocess; |
| |
| bool test_types_and_convertions() |
| { |
| typedef intersegment_ptr<int> pint_t; |
| typedef intersegment_ptr<const int> pcint_t; |
| typedef intersegment_ptr<volatile int> pvint_t; |
| typedef intersegment_ptr<const volatile int> pcvint_t; |
| |
| if(!detail::is_same<pint_t::value_type, int>::value) |
| return false; |
| if(!detail::is_same<pcint_t::value_type, const int>::value) |
| return false; |
| if(!detail::is_same<pvint_t::value_type, volatile int>::value) |
| return false; |
| if(!detail::is_same<pcvint_t::value_type, const volatile int>::value) |
| return false; |
| int dummy_int = 9; |
| |
| { pint_t pint(&dummy_int); pcint_t pcint(pint); |
| if(pcint.get() != &dummy_int) return false; } |
| { pint_t pint(&dummy_int); pvint_t pvint(pint); |
| if(pvint.get() != &dummy_int) return false; } |
| { pint_t pint(&dummy_int); pcvint_t pcvint(pint); |
| if(pcvint.get() != &dummy_int) return false; } |
| { pcint_t pcint(&dummy_int); pcvint_t pcvint(pcint); |
| if(pcvint.get() != &dummy_int) return false; } |
| { pvint_t pvint(&dummy_int); pcvint_t pcvint(pvint); |
| if(pcvint.get() != &dummy_int) return false; } |
| |
| pint_t pint(0); |
| pcint_t pcint(0); |
| pvint_t pvint(0); |
| pcvint_t pcvint(0); |
| |
| pint = &dummy_int; |
| pcint = &dummy_int; |
| pvint = &dummy_int; |
| pcvint = &dummy_int; |
| |
| { pcint = pint; if(pcint.get() != &dummy_int) return false; } |
| { pvint = pint; if(pvint.get() != &dummy_int) return false; } |
| { pcvint = pint; if(pcvint.get() != &dummy_int) return false; } |
| { pcvint = pcint; if(pcvint.get() != &dummy_int) return false; } |
| { pcvint = pvint; if(pcvint.get() != &dummy_int) return false; } |
| |
| if(!pint) |
| return false; |
| |
| pint = 0; |
| if(pint) |
| return false; |
| |
| return true; |
| } |
| |
| bool test_arithmetic() |
| { |
| typedef intersegment_ptr<int> pint_t; |
| const int NumValues = 5; |
| int values[NumValues]; |
| |
| //Initialize p |
| pint_t p = values; |
| if(p.get() != values) |
| return false; |
| |
| //Initialize p + NumValues |
| pint_t pe = &values[NumValues]; |
| if(pe == p) |
| return false; |
| if(pe.get() != &values[NumValues]) |
| return false; |
| |
| //ptr - ptr |
| if((pe - p) != NumValues) |
| return false; |
| //ptr - integer |
| if((pe - NumValues) != p) |
| return false; |
| //ptr + integer |
| if((p + NumValues) != pe) |
| return false; |
| //integer + ptr |
| if((NumValues + p) != pe) |
| return false; |
| //indexing |
| if(pint_t(&p[NumValues]) != pe) |
| return false; |
| if(pint_t(&pe[-NumValues]) != p) |
| return false; |
| |
| //ptr -= integer |
| pint_t p0 = pe; |
| p0-= NumValues; |
| if(p != p0) |
| return false; |
| //ptr += integer |
| pint_t penew = p0; |
| penew += NumValues; |
| if(penew != pe) |
| return false; |
| |
| //++ptr |
| penew = p0; |
| for(int j = 0; j != NumValues; ++j, ++penew); |
| if(penew != pe) |
| return false; |
| //--ptr |
| p0 = pe; |
| for(int j = 0; j != NumValues; ++j, --p0); |
| if(p != p0) |
| return false; |
| //ptr++ |
| penew = p0; |
| for(int j = 0; j != NumValues; ++j){ |
| pint_t p = penew; |
| if(p != penew++) |
| return false; |
| } |
| //ptr-- |
| p0 = pe; |
| for(int j = 0; j != NumValues; ++j){ |
| pint_t p = p0; |
| if(p != p0--) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool test_comparison() |
| { |
| typedef intersegment_ptr<int> pint_t; |
| const int NumValues = 5; |
| int values[NumValues]; |
| |
| //Initialize p |
| pint_t p = values; |
| if(p.get() != values) |
| return false; |
| |
| //Initialize p + NumValues |
| pint_t pe = &values[NumValues]; |
| if(pe == p) |
| return false; |
| if(pe.get() != &values[NumValues]) |
| return false; |
| |
| //operators |
| if(p == pe) |
| return false; |
| if(p != p) |
| return false; |
| if(!(p < pe)) |
| return false; |
| if(!(p <= pe)) |
| return false; |
| if(!(pe > p)) |
| return false; |
| if(!(pe >= p)) |
| return false; |
| |
| return true; |
| } |
| |
| struct segment_data |
| { |
| int int0; |
| int int1; |
| intersegment_ptr<int> ptr0; |
| int int2; |
| int int3; |
| }; |
| |
| bool test_basic_comparisons() |
| { |
| //Create aligned sections |
| const std::size_t PageSize = mapped_region::get_page_size(); |
| mapped_region reg_0_0(anonymous_shared_memory(PageSize)); |
| mapped_region reg_0_1(anonymous_shared_memory(PageSize)); |
| mapped_region reg_1_0(anonymous_shared_memory(PageSize)); |
| mapped_region reg_1_1(anonymous_shared_memory(PageSize)); |
| |
| if(sizeof(segment_data) > mapped_region::get_page_size()) |
| return false; |
| |
| segment_data &seg_0_0 = *static_cast<segment_data *>(reg_0_0.get_address()); |
| segment_data &seg_0_1 = *static_cast<segment_data *>(reg_0_1.get_address()); |
| segment_data &seg_1_0 = *static_cast<segment_data *>(reg_1_0.get_address()); |
| segment_data &seg_1_1 = *static_cast<segment_data *>(reg_1_1.get_address()); |
| |
| //Some dummy multi_segment_services |
| multi_segment_services *services0 = static_cast<multi_segment_services *>(0); |
| multi_segment_services *services1 = reinterpret_cast<multi_segment_services *>(1); |
| |
| const intersegment_ptr<int>::segment_group_id group_0_id = |
| intersegment_ptr<int>::new_segment_group(services0); |
| const intersegment_ptr<int>::segment_group_id group_1_id = |
| intersegment_ptr<int>::new_segment_group(services1); |
| |
| { |
| |
| //Now register the segments in the segment data-base |
| intersegment_ptr<int>::insert_mapping(group_0_id, &seg_0_0, PageSize); |
| intersegment_ptr<int>::insert_mapping(group_0_id, &seg_0_1, PageSize); |
| intersegment_ptr<int>::insert_mapping(group_1_id, &seg_1_0, PageSize); |
| intersegment_ptr<int>::insert_mapping(group_1_id, &seg_1_1, PageSize); |
| } |
| |
| //Now do some testing... |
| { |
| //Same segment |
| seg_0_0.ptr0 = &seg_0_0.int0; |
| seg_0_1.ptr0 = &seg_0_1.int0; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_0.int0) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_1.int0) |
| return false; |
| |
| //Try it again to make use of the already established relative addressing |
| seg_0_0.ptr0 = &seg_0_0.int1; |
| seg_0_1.ptr0 = &seg_0_1.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_0.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_1.int1) |
| return false; |
| |
| //Set to null and try again |
| seg_0_0.ptr0 = 0; |
| seg_0_1.ptr0 = 0; |
| |
| seg_0_0.ptr0 = &seg_0_0.int1; |
| seg_0_1.ptr0 = &seg_0_1.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_0.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_1.int1) |
| return false; |
| |
| //Set to null and try again |
| int stack_int; |
| seg_0_0.ptr0 = &stack_int; |
| seg_0_1.ptr0 = &stack_int; |
| |
| if(seg_0_0.ptr0.get() != &stack_int) |
| return false; |
| if(seg_0_1.ptr0.get() != &stack_int) |
| return false; |
| } |
| |
| { |
| //Now use stack variables |
| intersegment_ptr<int> stack_0 = &seg_0_0.int2; |
| intersegment_ptr<int> stack_1 = &seg_1_1.int2; |
| |
| if(stack_0.get() != &seg_0_0.int2) |
| return false; |
| if(stack_1.get() != &seg_1_1.int2) |
| return false; |
| |
| //Now reuse stack variables knowing that there are on stack |
| stack_0 = &seg_0_0.int3; |
| stack_1 = &seg_1_1.int3; |
| |
| if(stack_0.get() != &seg_0_0.int3) |
| return false; |
| if(stack_1.get() != &seg_1_1.int3) |
| return false; |
| |
| //Now set to null and try it again |
| stack_0 = 0; |
| stack_1 = 0; |
| |
| stack_0 = &seg_0_0.int3; |
| stack_1 = &seg_1_1.int3; |
| |
| if(stack_0.get() != &seg_0_0.int3) |
| return false; |
| if(stack_1.get() != &seg_1_1.int3) |
| return false; |
| } |
| { |
| //Different segments in the same group |
| seg_0_0.ptr0 = &seg_0_1.int0; |
| seg_0_1.ptr0 = &seg_0_0.int0; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_1.int0) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_0.int0) |
| return false; |
| |
| //Try it again to make use of the already established segmented addressing |
| seg_0_0.ptr0 = &seg_0_1.int1; |
| seg_0_1.ptr0 = &seg_0_0.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_1.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_0.int1) |
| return false; |
| |
| //Set to null and try it again |
| seg_0_0.ptr0 = 0; |
| seg_0_1.ptr0 = 0; |
| |
| seg_0_0.ptr0 = &seg_0_1.int1; |
| seg_0_1.ptr0 = &seg_0_0.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_0_1.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_0_0.int1) |
| return false; |
| } |
| |
| { |
| //Different groups |
| seg_0_0.ptr0 = &seg_1_0.int0; |
| seg_0_1.ptr0 = &seg_1_1.int0; |
| |
| if(seg_0_0.ptr0.get() != &seg_1_0.int0) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_1_1.int0) |
| return false; |
| |
| //Try it again |
| seg_0_0.ptr0 = &seg_1_0.int1; |
| seg_0_1.ptr0 = &seg_1_1.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_1_0.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_1_1.int1) |
| return false; |
| |
| //Set null and try it again |
| seg_0_0.ptr0 = 0; |
| seg_0_1.ptr0 = 0; |
| |
| seg_0_0.ptr0 = &seg_1_0.int1; |
| seg_0_1.ptr0 = &seg_1_1.int1; |
| |
| if(seg_0_0.ptr0.get() != &seg_1_0.int1) |
| return false; |
| if(seg_0_1.ptr0.get() != &seg_1_1.int1) |
| return false; |
| } |
| |
| { |
| //Erase mappings |
| intersegment_ptr<int>::delete_group(group_0_id); |
| intersegment_ptr<int>::delete_group(group_1_id); |
| } |
| return true; |
| } |
| |
| bool test_multi_segment_shared_memory() |
| { |
| { |
| shared_memory_object::remove("kk0"); |
| managed_multi_shared_memory mshm(create_only, "kk", 4096); |
| } |
| |
| shared_memory_object::remove("kk0"); |
| return true; |
| } |
| |
| int main() |
| {/* |
| if(!test_types_and_convertions()) |
| return 1; |
| if(!test_arithmetic()) |
| return 1; |
| if(!test_comparison()) |
| return 1; |
| if(!test_basic_comparisons()) |
| return 1; |
| |
| if(!test_multi_segment_shared_memory()) |
| return 1; |
| */ |
| return 0; |
| } |
| |
| #include <boost/interprocess/detail/config_end.hpp> |