Optimize merge and sort with the utility unused_storage

This commit is contained in:
Ion Gaztañaga
2024-09-09 00:40:15 +02:00
parent bd8c8b0327
commit 69136f9967
2 changed files with 48 additions and 33 deletions

View File

@ -121,6 +121,7 @@ namespace boost {
namespace container {
namespace dtl {
///////////////////////////////////////
//
// Helper functions to merge elements
@ -138,14 +139,19 @@ template<class SequenceContainer, class Compare>
inline void flat_tree_container_inplace_merge //is_contiguous_container == true
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
{
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
value_type *const braw = boost::movelib::to_raw_pointer(dest.data());
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
//Don't use iterator_to_raw_pointer for end as debug iterators can assert when
//"operator ->" is used with the end iterator
value_type *const eraw = braw + dest.size();
size_type dest_unused_storage_size = 0;
value_type *const dest_unused_storage_addr =
unused_storage<SequenceContainer>::get(dest, dest_unused_storage_size);
boost::movelib::adaptive_merge
(braw, iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
(braw, iraw, eraw, comp, dest_unused_storage_addr, dest_unused_storage_size);
}
template<class SequenceContainer, class Compare>
@ -164,15 +170,19 @@ template<class SequenceContainer, class Compare>
inline void flat_tree_container_inplace_sort_ending //is_contiguous_container == true
(SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
{
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
//Don't use iterator_to_raw_pointer for end as debug iterators can assert when
//"operator ->" is used with the end iterator
value_type* const eraw = boost::movelib::to_raw_pointer(dest.data()) + dest.size();
size_type dest_unused_storage_size;
value_type* const dest_unused_storage_addr =
unused_storage<SequenceContainer>::get(dest, dest_unused_storage_size);
boost::movelib::adaptive_sort
(iraw, eraw, comp, eraw, back_free_capacity<SequenceContainer>::get(dest));
(iraw, eraw, comp, dest_unused_storage_addr, dest_unused_storage_size);
}
template<class SequenceContainer, class Compare>
@ -320,23 +330,24 @@ template<class SequenceContainer, class Compare>
void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
(SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
{
if(tseq.capacity() >= (seq.capacity() - seq.size())) {
tseq.clear();
boost::movelib::adaptive_sort
(boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, boost::movelib::iterator_to_raw_pointer(tseq.begin())
, tseq.capacity());
}
else{
boost::movelib::adaptive_sort
(boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, boost::movelib::iterator_to_raw_pointer(seq.end())
, seq.capacity() - seq.size());
}
typedef typename SequenceContainer::value_type value_type;
typedef typename SequenceContainer::size_type size_type;
size_type tseq_unused_storage_size, seq_unused_storage_size;
value_type* const tseq_unused_storage_addr =
unused_storage<SequenceContainer>::get(tseq, tseq_unused_storage_size);
value_type* const seq_unused_storage_addr =
unused_storage<SequenceContainer>::get(seq, seq_unused_storage_size);
tseq.clear();
const bool use_tseq_storage = tseq_unused_storage_size > seq_unused_storage_size;
boost::movelib::adaptive_sort
( boost::movelib::iterator_to_raw_pointer(seq.begin())
, boost::movelib::iterator_to_raw_pointer(seq.end())
, comp
, use_tseq_storage ? tseq_unused_storage_addr : seq_unused_storage_addr
, use_tseq_storage ? tseq_unused_storage_size : seq_unused_storage_size);
}
template<class SequenceContainer, class Compare>

View File

@ -31,9 +31,9 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
//back_free_capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME back_free_capacity
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace back_free_capacity_detail {
//free_storage
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME unused_storage
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace unused_storage_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
@ -60,19 +60,23 @@ struct is_contiguous_container
template < class Container
, bool = boost::container::back_free_capacity_detail::
has_member_function_callable_with_back_free_capacity<const Container>::value>
struct back_free_capacity
, bool = boost::container::unused_storage_detail::
has_member_function_callable_with_unused_storage<const Container>::value>
struct unused_storage
{
static typename Container::size_type get(const Container &c)
{ return c.back_free_capacity(); }
static typename Container::value_type* get(Container &c, typename Container::size_type &s)
{ return c.unused_storage(s); }
};
template < class Container>
struct back_free_capacity<Container, false>
struct unused_storage<Container, false>
{
static typename Container::size_type get(const Container &c)
{ return c.capacity() - c.size(); }
static typename Container::value_type* get(Container&, typename Container::size_type &s)
{
s = 0;
return 0;
}
};
} //namespace dtl {