mirror of
https://github.com/boostorg/container.git
synced 2025-07-31 04:57:16 +02:00
Optimize merge and sort with the utility unused_storage
This commit is contained in:
@ -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>
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user