Skip to content

Commit

Permalink
Optimize merge and sort with the utility unused_storage
Browse files Browse the repository at this point in the history
  • Loading branch information
igaztanaga committed Sep 8, 2024
1 parent bd8c8b0 commit 69136f9
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 33 deletions.
55 changes: 33 additions & 22 deletions include/boost/container/detail/flat_tree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ namespace boost {
namespace container {
namespace dtl {


///////////////////////////////////////
//
// Helper functions to merge elements
Expand All @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
26 changes: 15 additions & 11 deletions include/boost/container/detail/is_contiguous_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down

0 comments on commit 69136f9

Please sign in to comment.