////////////////////////////////////////////////////////////////////////////// // Deallocate a raw buffer of bytes using an allocator ////////////////////////////////////////////////////////////////////////////// template<class Allocator> inline void deallocate( Allocator& a, byte* ptr, std::size_t nbytes = 0) { // Allocator element types typedef typename Allocator::value_type value_type; // Compute alignment values for fixing address BOOST_STATIC_CONSTANT(std::size_t, size = sizeof(value_type) ); BOOST_STATIC_CONSTANT(std::size_t, align = NT2_CONFIG_ALIGNMENT ); BOOST_STATIC_CONSTANT(std::size_t, fix = ~(std::size_t(align-1)) ); // How many elements are needed ot store proper number of bytes std::size_t nelems = align_on<size>(nbytes+align+sizeof(void*))/size; void* base = reinterpret_cast<void**>(ptr)[- 1]; a.deallocate(reinterpret_cast<typename Allocator::pointer>(base),nelems); }
byte* allocate( std::size_t nbytes ) { void *result; BOOST_STATIC_CONSTANT(std::size_t, align = NT2_CONFIG_ALIGNMENT ); #if defined(NT2_CONFIG_SUPPORT_POSIX_MEMALIGN) ////////////////////////////////////////////////////////////////////////////// // POSIX systems use posix_memalign ////////////////////////////////////////////////////////////////////////////// if(posix_memalign(&result, align, nbytes)) { NT2_THROW( std::bad_alloc() ); result = 0; } #elif defined (_MSC_VER) ////////////////////////////////////////////////////////////////////////////// // MSVC systems use _aligned_malloc ////////////////////////////////////////////////////////////////////////////// if( !(result = _aligned_malloc(nbytes, align) ) ) { NT2_THROW( std::bad_alloc() ); result = 0; } #else ////////////////////////////////////////////////////////////////////////////// // Other systems do the funky pointer stashing ////////////////////////////////////////////////////////////////////////////// void *base; BOOST_STATIC_CONSTANT(std::size_t, fix = ~(std::size_t(align-1))); if( !(base = ::malloc(nbytes+align+sizeof(void*))) ) { NT2_THROW( std::bad_alloc() ); result = 0; } else { std::size_t ref = reinterpret_cast<std::size_t>(base)+sizeof(void*); std::size_t stashed = (ref & fix) + align; result = reinterpret_cast<void*>(stashed); reinterpret_cast<void**>(result)[-1] = base; } #endif return reinterpret_cast<byte*>(result); }
//////////////////////////////////////////////////////////////////////////// // Forward, non-periodic case //////////////////////////////////////////////////////////////////////////// inline result_type eval ( A0 const& a0, A1 const& a1 , boost::mpl::false_ const&, boost::mpl::true_ const& ) const { BOOST_STATIC_CONSTANT( std::size_t, card = boost::simd::meta::cardinal_of<result_type>::value ); BOOST_STATIC_CONSTANT( std::size_t, offset = std::size_t(A3::value)/card*card ); BOOST_STATIC_CONSTANT( std::size_t, bytes = 16u/card ); BOOST_STATIC_CONSTANT( std::size_t, shifta = bytes*(A3::value%card) ); BOOST_STATIC_CONSTANT( std::size_t, shiftb = bytes*(card-A3::value%card) ); typedef typename dispatch::meta::as_integer<result_type>::type itype; result_type a = boost::simd::load<result_type>(a0,a1+offset); result_type b = boost::simd::load<result_type>(a0,a1+offset+card); __m128i sa = _mm_srli_si128(boost::simd::bitwise_cast<itype>(a.data_),shifta); __m128i sb = _mm_slli_si128(boost::simd::bitwise_cast<itype>(b.data_),shiftb); return boost::simd::bitwise_cast<result_type>(_mm_or_si128(sa,sb)); }
//////////////////////////////////////////////////////////////////////////// // Periodic case - Just add up to the runtime offset //////////////////////////////////////////////////////////////////////////// template<class Fwd> inline result_type eval( A0 const& a0, A1 const& a1, boost::mpl::true_ const&, Fwd const&) const { BOOST_STATIC_CONSTANT ( std::size_t , offset = std::size_t(A3::value) ); return boost::simd::load<result_type>(a0,a1+offset); }
//////////////////////////////////////////////////////////////////////////// // Forward, non-periodic case //////////////////////////////////////////////////////////////////////////// inline result_type eval ( A0 const& a0, A1 const& a1 , boost::mpl::false_ const&, boost::mpl::true_ const& ) const { BOOST_STATIC_CONSTANT( std::size_t, card = boost::simd::meta::cardinal_of<result_type>::value ); BOOST_STATIC_CONSTANT( std::size_t, offset = std::size_t(A3::value)/card ); BOOST_STATIC_CONSTANT( std::size_t, bytes = 16u/card ); BOOST_STATIC_CONSTANT( std::size_t, shifta = bytes*(A3::value%card) ); BOOST_STATIC_CONSTANT( std::size_t, shiftb = bytes*(card-A3::value%card) ); typedef typename boost::simd::meta::as_simd< typename meta::scalar_of<result_type>::type , boost::simd::tag::sse_ >::type raw_type; result_type a = boost::simd::load<result_type>(a0,a1+offset); result_type b = boost::simd::load<result_type>(a0,a1+offset+1); __m128i sa = _mm_srli_si128(boost::simd::bitwise_cast<__m128i>(a.data_),shifta); __m128i sb = _mm_slli_si128(boost::simd::bitwise_cast<__m128i>(b.data_),shiftb); result_type that = { boost::simd::bitwise_cast<raw_type>(_mm_or_si128(sa,sb)) }; return that; }
struct BOOST_PP_CAT(AUX778076_OP_PREFIX,_wknd) { BOOST_STATIC_CONSTANT(T, value = (n1 AUX778076_OP_TOKEN n2)); typedef integral_c<T,value> type; };
void sequenced_index_sort(Node* header,Compare comp) { /* Musser's mergesort, see http://www.cs.rpi.edu/~musser/gp/List/lists1.html. * The implementation is a little convoluted: in the original code * counter elements and carry are std::lists: here we do not want * to use multi_index instead, so we do things at a lower level, managing * directly the internal node representation. * Incidentally, the implementations I've seen of this algorithm (SGI, * Dinkumware, STLPort) are not exception-safe: this is. Moreover, we do not * use any dynamic storage. */ if(header->next()==header->impl()|| header->next()->next()==header->impl())return; BOOST_STATIC_CONSTANT( std::size_t, max_fill=(std::size_t)std::numeric_limits<std::size_t>::digits+1); aligned_storage< sizeof(sequenced_index_node_impl)> carry_spc; sequenced_index_node_impl& carry= *static_cast<sequenced_index_node_impl*>(carry_spc.address()); aligned_storage< sizeof( sequenced_index_node_impl[max_fill])> counter_spc; sequenced_index_node_impl* counter= static_cast<sequenced_index_node_impl*>(counter_spc.address()); std::size_t fill=0; carry.prior()=carry.next()=&carry; counter[0].prior()=counter[0].next()=&counter[0]; BOOST_TRY{ while(header->next()!=header->impl()){ sequenced_index_node_impl::relink(carry.next(),header->next()); std::size_t i=0; while(i<fill&&counter[i].next()!=&counter[i]){ sequenced_index_collate<Node>(&carry,&counter[i++],comp); } sequenced_index_node_impl::swap(&carry,&counter[i]); if(i==fill){ ++fill; counter[fill].prior()=counter[fill].next()=&counter[fill]; } } for(std::size_t i=1;i<fill;++i){ sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp); } sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]); } BOOST_CATCH(...) { sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry); for(std::size_t i=0;i<=fill;++i){ sequenced_index_node_impl::relink( header->impl(),counter[i].next(),&counter[i]); } BOOST_RETHROW; }
static void do_test(bool do_count_cleanup_time = false) { BOOST_STATIC_CONSTANT(std::size_t, c_run_count = 5000000); typedef std::vector<char> str_t; typedef boost::variant<int, str_t, float> var_t; const char hello1_c[] = "hello long word"; const str_t hello1(hello1_c, hello1_c + sizeof(hello1_c)); const char hello2_c[] = "Helllloooooooooooooooooooooooooooooooo!!!!!!!!!!!!!"; const str_t hello2(hello2_c, hello2_c + sizeof(hello2_c)); if (do_count_cleanup_time) { std::cout << "#############################################\n"; std::cout << "#############################################\n"; std::cout << "NOW TIMES WITH DATA DESTRUCTION\n"; std::cout << "#############################################\n"; } std::vector<var_t> data_from, data_to; data_from.resize(c_run_count, hello1); data_to.reserve(c_run_count); { scope sc("boost::variant(const variant&) copying speed"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to.push_back(data_from[i]); } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } data_from.resize(c_run_count, hello1); data_to.clear(); data_to.reserve(c_run_count); { scope sc("boost::variant(variant&&) moving speed"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to.push_back(boost::move(data_from[i])); } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } std::cout << "#############################################\n"; data_from.clear(); data_from.resize(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, hello2); { scope sc("boost::variant=(const variant&) copying speed on same types"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = data_from[i]; } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } data_from.resize(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, hello2); { scope sc("boost::variant=(variant&&) moving speed on same types"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = boost::move(data_from[i]); } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } std::cout << "#############################################\n"; data_from.clear(); data_from.resize(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, var_t(0)); { scope sc("boost::variant=(const variant&) copying speed on different types"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = data_from[i]; } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } data_from.resize(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, var_t(0)); { scope sc("boost::variant=(variant&&) moving speed on different types"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = boost::move(data_from[i]); } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } std::cout << "#############################################\n"; data_from.clear(); data_from.resize(c_run_count, var_t(0)); data_to.clear(); data_to.resize(c_run_count, hello2); { scope sc("boost::variant=(const variant&) copying speed on different types II"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = data_from[i]; } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } data_from.resize(c_run_count, var_t(0)); data_to.clear(); data_to.resize(c_run_count, hello2); { scope sc("boost::variant=(variant&&) moving speed on different types II"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = boost::move(data_from[i]); } if (do_count_cleanup_time) { data_to.clear(); data_from.clear(); } } std::cout << "#############################################\n"; std::vector<str_t> s1(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, var_t(0)); { scope sc("boost::variant=(const T&) copying speed"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = s1[i]; } if (do_count_cleanup_time) { data_to.clear(); s1.clear(); } } std::vector<str_t> s2(c_run_count, hello2); data_to.clear(); data_to.resize(c_run_count, var_t(0)); { scope sc("boost::variant=(T&&) moving speed"); for (std::size_t i = 0; i < c_run_count; ++i) { data_to[i] = boost::move(s2[i]); } if (do_count_cleanup_time) { data_to.clear(); s2.clear(); } } }