350 lines
8.8 KiB
C++
350 lines
8.8 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (C) Copyright Ion Gaztanaga 2007-2012. 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/offset_ptr.hpp>
|
|
#include <boost/interprocess/detail/type_traits.hpp>
|
|
#include <boost/intrusive/pointer_traits.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
|
|
using namespace boost::interprocess;
|
|
|
|
class Base
|
|
{};
|
|
|
|
class Derived
|
|
: public Base
|
|
{};
|
|
|
|
class VirtualDerived
|
|
: public virtual Base
|
|
{};
|
|
|
|
bool test_types_and_conversions()
|
|
{
|
|
typedef offset_ptr<int> pint_t;
|
|
typedef offset_ptr<const int> pcint_t;
|
|
typedef offset_ptr<volatile int> pvint_t;
|
|
typedef offset_ptr<const volatile int> pcvint_t;
|
|
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pint_t::element_type, int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pcint_t::element_type, const int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pvint_t::element_type, volatile int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pcvint_t::element_type, const volatile int>::value));
|
|
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pint_t::value_type, int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pcint_t::value_type, int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pvint_t::value_type, int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<pcvint_t::value_type, int>::value));
|
|
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;
|
|
|
|
if(pint != 0)
|
|
return false;
|
|
|
|
if(0 != pint)
|
|
return false;
|
|
|
|
pint = &dummy_int;
|
|
if(0 == pint)
|
|
return false;
|
|
|
|
if(pint == 0)
|
|
return false;
|
|
|
|
pcint = &dummy_int;
|
|
|
|
if( (pcint - pint) != 0)
|
|
return false;
|
|
|
|
if( (pint - pcint) != 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
template<class BasePtr, class DerivedPtr>
|
|
bool test_base_derived_impl()
|
|
{
|
|
typename DerivedPtr::element_type d;
|
|
DerivedPtr pderi(&d);
|
|
|
|
BasePtr pbase(pderi);
|
|
pbase = pderi;
|
|
if(pbase != pderi)
|
|
return false;
|
|
if(!(pbase == pderi))
|
|
return false;
|
|
if((pbase - pderi) != 0)
|
|
return false;
|
|
if(pbase < pderi)
|
|
return false;
|
|
if(pbase > pderi)
|
|
return false;
|
|
if(!(pbase <= pderi))
|
|
return false;
|
|
if(!(pbase >= pderi))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test_base_derived()
|
|
{
|
|
typedef offset_ptr<Base> pbase_t;
|
|
typedef offset_ptr<const Base> pcbas_t;
|
|
typedef offset_ptr<Derived> pderi_t;
|
|
typedef offset_ptr<VirtualDerived> pvder_t;
|
|
|
|
if(!test_base_derived_impl<pbase_t, pderi_t>())
|
|
return false;
|
|
if(!test_base_derived_impl<pbase_t, pvder_t>())
|
|
return false;
|
|
if(!test_base_derived_impl<pcbas_t, pderi_t>())
|
|
return false;
|
|
if(!test_base_derived_impl<pcbas_t, pvder_t>())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test_arithmetic()
|
|
{
|
|
typedef offset_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_new_copy = penew;
|
|
if(p_new_copy != penew++)
|
|
return false;
|
|
}
|
|
//ptr--
|
|
p0 = pe;
|
|
for(int j = 0; j != NumValues; ++j){
|
|
pint_t p0_copy = p0;
|
|
if(p0_copy != p0--)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool test_comparison()
|
|
{
|
|
typedef offset_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;
|
|
}
|
|
|
|
bool test_pointer_traits()
|
|
{
|
|
typedef offset_ptr<int> OInt;
|
|
typedef boost::intrusive::pointer_traits< OInt > PTOInt;
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::element_type, int>::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::pointer, OInt >::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::difference_type, OInt::difference_type >::value));
|
|
BOOST_STATIC_ASSERT((ipcdetail::is_same<PTOInt::rebind_pointer<double>::type, offset_ptr<double> >::value));
|
|
int dummy;
|
|
OInt oi(&dummy);
|
|
if(boost::intrusive::pointer_traits<OInt>::pointer_to(dummy) != oi){
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
if(!test_types_and_conversions())
|
|
return 1;
|
|
if(!test_base_derived())
|
|
return 1;
|
|
if(!test_arithmetic())
|
|
return 1;
|
|
if(!test_comparison())
|
|
return 1;
|
|
if(!test_pointer_traits())
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
#include <boost/interprocess/detail/config_end.hpp>
|
|
|
|
/*
|
|
//Offset ptr benchmark
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <boost/interprocess/managed_shared_memory.hpp>
|
|
#include <boost/interprocess/containers/vector.hpp>
|
|
#include <boost/interprocess/allocators/allocator.hpp>
|
|
#include <boost/timer.hpp>
|
|
#include <cstddef>
|
|
|
|
template<class InIt,
|
|
class Ty> inline
|
|
Ty accumulate2(InIt First, InIt Last, Ty Val)
|
|
{ // return sum of Val and all in [First, Last)
|
|
for (; First != Last; ++First) //First = First + 1)
|
|
Val = Val + *First;
|
|
return (Val);
|
|
}
|
|
|
|
template <typename Vector>
|
|
void time_test(const Vector& vec, std::size_t iterations, const char* label) {
|
|
// assert(!vec.empty())
|
|
boost::timer t;
|
|
typename Vector::const_iterator first = vec.begin();
|
|
typename Vector::value_type result(0);
|
|
while (iterations != 0) {
|
|
result = accumulate2(first, first + vec.size(), result);
|
|
--iterations;
|
|
}
|
|
std::cout << label << t.elapsed() << " " << result << std::endl;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
using namespace boost::interprocess;
|
|
typedef allocator<double, managed_shared_memory::segment_manager> alloc_t;
|
|
|
|
std::size_t n = 0x1 << 26;
|
|
std::size_t file_size = n * sizeof(double) + 1000000;
|
|
|
|
{
|
|
shared_memory_object::remove("MyMappedFile");
|
|
managed_shared_memory segment(open_or_create, "MyMappedFile", file_size);
|
|
shared_memory_object::remove("MyMappedFile");
|
|
alloc_t alloc_inst(segment.get_segment_manager());
|
|
vector<double, alloc_t> v0(n, double(42.42), alloc_inst);
|
|
time_test(v0, 10, "iterator shared: ");
|
|
}
|
|
{
|
|
std::vector<double> v1(n, double(42.42));
|
|
time_test(v1, 10, "iterator non-shared: ");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
*/
|