binary_heap: Unify Extend implementation.
Previously the bulk rebuild specialization was only available with Vec, and for general iterators Extend only provided pre-allocation through reserve(). By using a drop guard, we can safely bulk rebuild even if the iterator may panic. This allows benefiting from the bulk rebuild optimization without collecting iterator elements into a Vec beforehand, which would nullify any performance gains from bulk rebuild.
This commit is contained in:
parent
11c589c046
commit
116bb4dfb2
@ -154,8 +154,6 @@ use crate::collections::TryReserveError;
|
||||
use crate::slice;
|
||||
use crate::vec::{self, AsVecIntoIter, Vec};
|
||||
|
||||
use super::SpecExtend;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@ -1715,7 +1713,8 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> {
|
||||
impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
||||
#[inline]
|
||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
<Self as SpecExtend<I>>::spec_extend(self, iter);
|
||||
let guard = RebuildOnDrop { rebuild_from: self.len(), heap: self };
|
||||
guard.heap.data.extend(iter);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -1729,37 +1728,6 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
|
||||
default fn spec_extend(&mut self, iter: I) {
|
||||
self.extend_desugared(iter.into_iter());
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> SpecExtend<Vec<T>> for BinaryHeap<T> {
|
||||
fn spec_extend(&mut self, ref mut other: Vec<T>) {
|
||||
let start = self.data.len();
|
||||
self.data.append(other);
|
||||
self.rebuild_tail(start);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> SpecExtend<BinaryHeap<T>> for BinaryHeap<T> {
|
||||
fn spec_extend(&mut self, ref mut other: BinaryHeap<T>) {
|
||||
self.append(other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> BinaryHeap<T> {
|
||||
fn extend_desugared<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
let iterator = iter.into_iter();
|
||||
let (lower, _) = iterator.size_hint();
|
||||
|
||||
self.reserve(lower);
|
||||
|
||||
iterator.for_each(move |elem| self.push(elem));
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "extend_ref", since = "1.2.0")]
|
||||
impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
|
||||
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user