re PR libstdc++/53263 (priority_queue is very slow if -D_GLIBCXX_DEBUG is used)

2012-05-11  François Dumont  <fdumont@gcc.gnu.org>

	PR libstdc++/53263
	* include/debug/safe_iterator.h (__gnu_debug::__base): Move...
	* include/debug/functions.h: ... Here. Add debug function
	overloads to perform checks on normal iterators when possible.
	* include/debug/macros.h (__glibcxx_check_heap)
	(__glibcxx_check_heap_pred): Use __gnu_debug::__base on iterator range.

From-SVN: r187414
This commit is contained in:
François Dumont 2012-05-11 19:21:31 +00:00
parent 06118b14d6
commit 0545ebf2dc
4 changed files with 168 additions and 59 deletions

View File

@ -1,3 +1,12 @@
2012-05-11 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/53263
* include/debug/safe_iterator.h (__gnu_debug::__base): Move...
* include/debug/functions.h: ... Here. Add debug function
overloads to perform checks on normal iterators when possible.
* include/debug/macros.h (__glibcxx_check_heap)
(__glibcxx_check_heap_pred): Use __gnu_debug::__base on iterator range.
2012-05-10 DJ Delorie <dj@redhat.com>
* include/bits/random.tcc (seed_seq::generate): Cast max()

View File

@ -31,7 +31,8 @@
#define _GLIBCXX_DEBUG_FUNCTIONS_H 1
#include <bits/c++config.h>
#include <bits/stl_iterator_base_types.h> // for iterator_traits, categories
#include <bits/stl_iterator_base_types.h> // for iterator_traits, categories and
// _Iter_base
#include <bits/cpp_type_traits.h> // for __is_integer
#include <debug/formatter.h>
@ -118,11 +119,8 @@ namespace __gnu_debug
inline bool
__valid_range_aux(const _InputIterator& __first,
const _InputIterator& __last, std::__false_type)
{
typedef typename std::iterator_traits<_InputIterator>::iterator_category
_Category;
return __valid_range_aux2(__first, __last, _Category());
}
{ return __valid_range_aux2(__first, __last,
std::__iterator_category(__first)); }
/** Don't know what these iterators are, or if they are even
* iterators (we may get an integral type for InputIterator), so
@ -214,6 +212,15 @@ namespace __gnu_debug
return true;
}
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence>
inline bool
__check_sorted_aux(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
std::random_access_iterator_tag __tag)
{ return __check_sorted_aux(__first.base(), __last.base(), __tag); }
// Can't check if an input iterator sequence is sorted, because we can't step
// through the sequence.
template<typename _InputIterator, typename _Predicate>
@ -240,19 +247,28 @@ namespace __gnu_debug
return true;
}
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence,
typename _Predicate>
inline bool
__check_sorted_aux(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
_Predicate __pred,
std::random_access_iterator_tag __tag)
{ return __check_sorted_aux(__first.base(), __last.base(), __pred, __tag); }
// Determine if a sequence is sorted.
template<typename _InputIterator>
inline bool
__check_sorted(const _InputIterator& __first, const _InputIterator& __last)
{
typedef typename std::iterator_traits<_InputIterator>::iterator_category
_Category;
// Verify that the < operator for elements in the sequence is a
// StrictWeakOrdering by checking that it is irreflexive.
__glibcxx_assert(__first == __last || !(*__first < *__first));
return __check_sorted_aux(__first, __last, _Category());
return __check_sorted_aux(__first, __last,
std::__iterator_category(__first));
}
template<typename _InputIterator, typename _Predicate>
@ -260,14 +276,12 @@ namespace __gnu_debug
__check_sorted(const _InputIterator& __first, const _InputIterator& __last,
_Predicate __pred)
{
typedef typename std::iterator_traits<_InputIterator>::iterator_category
_Category;
// Verify that the predicate is StrictWeakOrdering by checking that it
// is irreflexive.
__glibcxx_assert(__first == __last || !__pred(*__first, *__first));
return __check_sorted_aux(__first, __last, __pred, _Category());
return __check_sorted_aux(__first, __last, __pred,
std::__iterator_category(__first));
}
template<typename _InputIterator>
@ -332,13 +346,11 @@ namespace __gnu_debug
return __check_sorted_set_aux(__first, __last, __pred, _SameType());
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 270. Binary search requirements overly strict
// Determine if a sequence is partitioned w.r.t. this element.
template<typename _ForwardIterator, typename _Tp>
inline bool
__check_partitioned_lower(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value)
__check_partitioned_lower_aux(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
std::forward_iterator_tag)
{
while (__first != __last && *__first < __value)
++__first;
@ -347,10 +359,33 @@ namespace __gnu_debug
return __first == __last;
}
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence, typename _Tp>
inline bool
__check_partitioned_lower_aux(
const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
const _Tp& __value,
std::random_access_iterator_tag __tag)
{ return __check_partitioned_lower_aux(__first.base(), __last.base(),
__value, __tag); }
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 270. Binary search requirements overly strict
// Determine if a sequence is partitioned w.r.t. this element.
template<typename _ForwardIterator, typename _Tp>
inline bool
__check_partitioned_upper(_ForwardIterator __first,
__check_partitioned_lower(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value)
{ return __check_partitioned_lower_aux(__first, __last, __value,
std::__iterator_category(__first)); }
template<typename _ForwardIterator, typename _Tp>
inline bool
__check_partitioned_upper_aux(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
std::forward_iterator_tag)
{
while (__first != __last && !(__value < *__first))
++__first;
@ -359,12 +394,31 @@ namespace __gnu_debug
return __first == __last;
}
// Determine if a sequence is partitioned w.r.t. this element.
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence, typename _Tp>
inline bool
__check_partitioned_upper_aux(
const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
const _Tp& __value,
std::random_access_iterator_tag __tag)
{ return __check_partitioned_upper_aux(__first.base(), __last.base(),
__value, __tag); }
template<typename _ForwardIterator, typename _Tp>
inline bool
__check_partitioned_upper(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value)
{ return __check_partitioned_upper_aux(__first, __last, __value,
std::__iterator_category(__first)); }
template<typename _ForwardIterator, typename _Tp, typename _Pred>
inline bool
__check_partitioned_lower(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
_Pred __pred)
__check_partitioned_lower_aux(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
_Pred __pred,
std::forward_iterator_tag)
{
while (__first != __last && bool(__pred(*__first, __value)))
++__first;
@ -373,11 +427,34 @@ namespace __gnu_debug
return __first == __last;
}
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence,
typename _Tp, typename _Pred>
inline bool
__check_partitioned_lower_aux(
const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
const _Tp& __value, _Pred __pred,
std::random_access_iterator_tag __tag)
{ return __check_partitioned_lower_aux(__first.base(), __last.base(),
__value, __pred, __tag); }
// Determine if a sequence is partitioned w.r.t. this element.
template<typename _ForwardIterator, typename _Tp, typename _Pred>
inline bool
__check_partitioned_upper(_ForwardIterator __first,
__check_partitioned_lower(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
_Pred __pred)
{ return __check_partitioned_lower_aux(__first, __last, __value, __pred,
std::__iterator_category(__first)); }
template<typename _ForwardIterator, typename _Tp, typename _Pred>
inline bool
__check_partitioned_upper_aux(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
_Pred __pred,
std::forward_iterator_tag)
{
while (__first != __last && !bool(__pred(__value, *__first)))
++__first;
@ -385,6 +462,58 @@ namespace __gnu_debug
++__first;
return __first == __last;
}
// For performance reason, as the iterator range has been validated, check on
// random access safe iterators is done using the base iterator.
template<typename _Iterator, typename _Sequence,
typename _Tp, typename _Pred>
inline bool
__check_partitioned_upper_aux(
const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
const _Tp& __value, _Pred __pred,
std::random_access_iterator_tag __tag)
{ return __check_partitioned_upper_aux(__first.base(), __last.base(),
__value, __pred, __tag); }
template<typename _ForwardIterator, typename _Tp, typename _Pred>
inline bool
__check_partitioned_upper(_ForwardIterator __first,
_ForwardIterator __last, const _Tp& __value,
_Pred __pred)
{ return __check_partitioned_upper_aux(__first, __last, __value, __pred,
std::__iterator_category(__first)); }
// Helper struct to detect random access safe iterators.
template<typename _Iterator>
struct __is_safe_random_iterator
{
enum { __value = 0 };
typedef std::__false_type __type;
};
template<typename _Iterator, typename _Sequence>
struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
: std::__are_same<std::random_access_iterator_tag,
typename std::iterator_traits<_Iterator>::
iterator_category>
{ };
template<typename _Iterator>
struct _Siter_base
: std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
{ };
/** Helper function to extract base iterator of random access safe iterator
in order to reduce performance impact of debug mode. Limited to random
access iterator because it is the only category for which it is possible
to check for correct iterators order in the __valid_range function
thanks to the < operator.
*/
template<typename _Iterator>
inline typename _Siter_base<_Iterator>::iterator_type
__base(_Iterator __it)
{ return _Siter_base<_Iterator>::_S_base(__it); }
} // namespace __gnu_debug
#endif

View File

@ -296,7 +296,8 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper(_First, _Last, \
// Verify that the iterator range [_First, _Last) is a heap
#define __glibcxx_check_heap(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(std::__is_heap(_First, _Last), \
_GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \
__gnu_debug::__base(_Last)), \
_M_message(__gnu_debug::__msg_not_heap) \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
@ -304,7 +305,9 @@ _GLIBCXX_DEBUG_VERIFY(std::__is_heap(_First, _Last), \
/** Verify that the iterator range [_First, _Last) is a heap
w.r.t. the predicate _Pred. */
#define __glibcxx_check_heap_pred(_First,_Last,_Pred) \
_GLIBCXX_DEBUG_VERIFY(std::__is_heap(_First, _Last, _Pred), \
_GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \
__gnu_debug::__base(_Last), \
_Pred), \
_M_message(__gnu_debug::__msg_not_heap_pred) \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \

View File

@ -35,7 +35,6 @@
#include <debug/functions.h>
#include <debug/safe_base.h>
#include <bits/stl_pair.h>
#include <bits/stl_iterator_base_types.h> // for _Iter_base
#include <ext/type_traits.h>
namespace __gnu_debug
@ -714,37 +713,6 @@ namespace __gnu_debug
operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
const _Safe_iterator<_Iterator, _Sequence>& __i)
{ return __i + __n; }
// Helper struct to detect random access safe iterators.
template<typename _Iterator>
struct __is_safe_random_iterator
{
enum { __value = 0 };
typedef std::__false_type __type;
};
template<typename _Iterator, typename _Sequence>
struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
: std::__are_same<std::random_access_iterator_tag,
typename std::iterator_traits<_Iterator>::
iterator_category>
{ };
template<typename _Iterator>
struct _Siter_base
: std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
{ };
/** Helper function to extract base iterator of random access safe iterator
in order to reduce performance impact of debug mode. Limited to random
access iterator because it is the only category for which it is possible
to check for correct iterators order in the __valid_range function
thanks to the < operator.
*/
template<typename _Iterator>
inline typename _Siter_base<_Iterator>::iterator_type
__base(_Iterator __it)
{ return _Siter_base<_Iterator>::_S_base(__it); }
} // namespace __gnu_debug
#include <debug/safe_iterator.tcc>