diff --git a/hpx/parallel/util/transfer.hpp b/hpx/parallel/util/transfer.hpp index b73832af65e6..852816560bf9 100644 --- a/hpx/parallel/util/transfer.hpp +++ b/hpx/parallel/util/transfer.hpp @@ -7,6 +7,7 @@ #define HPX_PARALLEL_UTIL_TRANSFER_MAY_06_2016_0140PM #include +#include #include #include // for std::memmove @@ -20,79 +21,8 @@ namespace hpx { namespace parallel { namespace util /////////////////////////////////////////////////////////////////////////// namespace detail { - struct general_pointer_tag {}; - - template - inline general_pointer_tag - get_pointer_category(Source const&, Dest const&) - { - return general_pointer_tag(); - } #if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) - // We know that we can optimize copy operations if the iterators are - // pointers and if the value_type is layout compatible. - struct trivially_copyable_pointer_tag : general_pointer_tag {}; - - template - struct pointer_category - { - typedef typename std::conditional< - std::integral_constant::value && - std::is_integral::value && - std::is_integral::value && - !std::is_volatile::value && - !std::is_volatile::value && - (std::is_same::value == - std::is_same::value), - trivially_copyable_pointer_tag, - general_pointer_tag - >::type type; - }; - - // every type is layout-compatible with itself - template - struct pointer_category - { - typedef typename std::conditional< - std::is_trivially_copyable::value, - trivially_copyable_pointer_tag, - general_pointer_tag - >::type type; - }; - - // pointers are layout compatible - template - struct pointer_category - { - typedef trivially_copyable_pointer_tag type; - }; - - // isolate iterators which are pointers and their value_types are - // assignable - template - inline typename std::conditional< - std::is_assignable::value, - typename pointer_category< - typename std::remove_reference::type, Dest - >::type, - general_pointer_tag - >::type - get_pointer_category(Source* const&, Dest* const&) - { - typedef typename std::conditional< - std::is_assignable::value, - typename pointer_category< - typename std::remove_reference::type, Dest - >::type, - general_pointer_tag - >::type category_type; - - return category_type(); - } - /////////////////////////////////////////////////////////////////////// template HPX_FORCEINLINE static std::pair @@ -102,10 +32,12 @@ namespace hpx { namespace parallel { namespace util std::is_pointer::value, "optimized copy is possible for pointer-iterators only"); + typedef typename std::iterator_traits::value_type data_type; + const char* const first_ch = reinterpret_cast(first); char* const dest_ch = reinterpret_cast(dest); - std::memmove(dest_ch, first_ch, count); + std::memmove(dest_ch, first_ch, count * sizeof(data_type)); std::advance(first, count); std::advance(dest, count); @@ -130,7 +62,7 @@ namespace hpx { namespace parallel { namespace util #if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) template <> - struct copy_helper + struct copy_helper { template HPX_FORCEINLINE static std::pair @@ -146,7 +78,7 @@ namespace hpx { namespace parallel { namespace util HPX_FORCEINLINE std::pair copy_helper(InIter first, InIter last, OutIter dest) { - typedef decltype(detail::get_pointer_category(first, dest)) category; + typedef decltype(hpx::traits::get_pointer_category(first, dest)) category; return detail::copy_helper::call(first, last, dest); } @@ -169,7 +101,7 @@ namespace hpx { namespace parallel { namespace util #if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) template <> - struct copy_n_helper + struct copy_n_helper { template HPX_FORCEINLINE static std::pair @@ -185,7 +117,7 @@ namespace hpx { namespace parallel { namespace util HPX_FORCEINLINE std::pair copy_n_helper(InIter first, std::size_t count, OutIter dest) { - typedef decltype(detail::get_pointer_category(first, dest)) category; + typedef decltype(hpx::traits::get_pointer_category(first, dest)) category; return detail::copy_n_helper::call(first, count, dest); } @@ -208,7 +140,7 @@ namespace hpx { namespace parallel { namespace util #if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) template <> - struct move_helper + struct move_helper { template HPX_FORCEINLINE static std::pair @@ -224,7 +156,7 @@ namespace hpx { namespace parallel { namespace util HPX_FORCEINLINE std::pair move_helper(InIter first, InIter last, OutIter dest) { - typedef decltype(detail::get_pointer_category(first, dest)) category; + typedef decltype(hpx::traits::get_pointer_category(first, dest)) category; return detail::move_helper::call(first, last, dest); } @@ -247,7 +179,7 @@ namespace hpx { namespace parallel { namespace util #if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) template <> - struct move_n_helper + struct move_n_helper { template HPX_FORCEINLINE static std::pair @@ -263,7 +195,7 @@ namespace hpx { namespace parallel { namespace util HPX_FORCEINLINE std::pair move_n_helper(InIter first, std::size_t count, OutIter dest) { - typedef decltype(detail::get_pointer_category(first, dest)) category; + typedef decltype(hpx::traits::get_pointer_category(first, dest)) category; return detail::move_n_helper::call(first, count, dest); } }}} diff --git a/hpx/traits.hpp b/hpx/traits.hpp index 6e0bb05cc2cd..edbd68925be3 100644 --- a/hpx/traits.hpp +++ b/hpx/traits.hpp @@ -229,6 +229,16 @@ namespace hpx { namespace traits template struct is_executor_parameters; + + /////////////////////////////////////////////////////////////////////////// + struct general_pointer_tag {}; + +#if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) + struct trivially_copyable_pointer_tag : general_pointer_tag {}; +#endif + + template + general_pointer_tag get_pointer_category(Source const&, Dest const&); }} #endif diff --git a/hpx/traits/pointer_category.hpp b/hpx/traits/pointer_category.hpp new file mode 100644 index 000000000000..256618014bfb --- /dev/null +++ b/hpx/traits/pointer_category.hpp @@ -0,0 +1,95 @@ +// Copyright (c) 2016 Hartmut Kaiser +// Copyright (c) 2016 John Biddiscombe +// +// 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) + +#if !defined(HPX_TRAITS_POINTER_CATEGORY_MAY_10_2016) +#define HPX_TRAITS_POINTER_CATEGORY_MAY_10_2016 + +#include + +#include + +// Select a copy tag type to enable optimization +// of copy/move operations if the iterators are +// pointers and if the value_type is layout compatible. + +namespace hpx { namespace traits +{ + + template + inline general_pointer_tag + get_pointer_category(Source const&, Dest const&) + { + return general_pointer_tag(); + } + +#if defined(HPX_HAVE_CXX11_IS_TRIVIALLY_COPYABLE) + + namespace detail { + + template + struct pointer_category + { + typedef typename std::conditional< + std::integral_constant::value && + std::is_integral::value && + std::is_integral::value && + !std::is_volatile::value && + !std::is_volatile::value && + (std::is_same::value == + std::is_same::value), + trivially_copyable_pointer_tag, + general_pointer_tag + >::type type; + }; + + // every type is layout-compatible with itself + template + struct pointer_category + { + typedef typename std::conditional< + std::is_trivially_copyable::value, + trivially_copyable_pointer_tag, + general_pointer_tag + >::type type; + }; + + // pointers are layout compatible + template + struct pointer_category + { + typedef trivially_copyable_pointer_tag type; + }; + } + + // isolate iterators which are pointers and their value_types are + // assignable + template + inline typename std::conditional< + std::is_assignable::value, + typename detail::pointer_category< + typename std::remove_const::type, Dest + >::type, + general_pointer_tag + >::type + get_pointer_category(Source* const&, Dest* const&) + { + typedef typename std::conditional< + std::is_assignable::value, + typename detail::pointer_category< + typename std::remove_const::type, Dest + >::type, + general_pointer_tag + >::type category_type; + + return category_type(); + } +#endif + +}} + +#endif