Skip to content

Commit

Permalink
binary_heap: Unify Extend implementation.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ishitatsuyuki committed Feb 25, 2023
1 parent a4d2738 commit cd3ee19
Showing 1 changed file with 2 additions and 34 deletions.
36 changes: 2 additions & 34 deletions collections/binary_heap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ use crate::collections::TryReserveError;
use crate::slice;
use crate::vec::{self, AsVecIntoIter, Vec};

use super::SpecExtend;

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -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]
Expand All @@ -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) {
Expand Down

0 comments on commit cd3ee19

Please sign in to comment.