@@ -13,7 +13,7 @@ use crate::alloc::{Allocator, Global};
1313
1414use super :: borrow:: DormantMutRef ;
1515use super :: dedup_sorted_iter:: DedupSortedIter ;
16- use super :: navigate:: { LazyLeafRange , LeafRange } ;
16+ use super :: navigate:: { LazyLeafRange , LeafRange , RootVessel } ;
1717use super :: node:: { self , marker, ForceResult :: * , Handle , NodeRef , Root } ;
1818use super :: search:: SearchResult :: * ;
1919
@@ -559,6 +559,7 @@ impl<K, V> BTreeMap<K, V> {
559559
560560impl < K , V , A : Allocator > BTreeMap < K , V , A > {
561561 /// Clears the map, removing all elements.
562+ /// Keeps a part of the allocated memory for reuse.
562563 ///
563564 /// # Examples
564565 ///
@@ -574,12 +575,18 @@ impl<K, V, A: Allocator> BTreeMap<K, V, A> {
574575 /// ```
575576 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
576577 pub fn clear ( & mut self ) {
577- // avoid moving the allocator
578- mem:: drop ( BTreeMap {
579- root : mem:: replace ( & mut self . root , None ) ,
580- length : mem:: replace ( & mut self . length , 0 ) ,
581- alloc : ManuallyDrop :: new ( & * self . alloc ) ,
582- } ) ;
578+ if let Some ( root) = self . root . take ( ) {
579+ let mut iter = IntoIter {
580+ range : root. into_dying ( ) . full_range ( ) ,
581+ length : self . length ,
582+ alloc : unsafe { ManuallyDrop :: take ( & mut self . alloc ) } ,
583+ } ;
584+ self . length = 0 ;
585+ while let Some ( kv) = iter. dying_next ( Some ( & mut self . root ) ) {
586+ // SAFETY: we consume the dying handle immediately.
587+ unsafe { kv. drop_key_val ( ) } ;
588+ }
589+ }
583590 }
584591
585592 /// Makes a new empty BTreeMap with a reasonable choice for B.
@@ -1606,14 +1613,14 @@ impl<K, V, A: Allocator> Drop for IntoIter<K, V, A> {
16061613 fn drop ( & mut self ) {
16071614 // Continue the same loop we perform below. This only runs when unwinding, so we
16081615 // don't have to care about panics this time (they'll abort).
1609- while let Some ( kv) = self . 0 . dying_next ( ) {
1616+ while let Some ( kv) = self . 0 . dying_next ( None ) {
16101617 // SAFETY: we consume the dying handle immediately.
16111618 unsafe { kv. drop_key_val ( ) } ;
16121619 }
16131620 }
16141621 }
16151622
1616- while let Some ( kv) = self . dying_next ( ) {
1623+ while let Some ( kv) = self . dying_next ( None ) {
16171624 let guard = DropGuard ( self ) ;
16181625 // SAFETY: we don't touch the tree before consuming the dying handle.
16191626 unsafe { kv. drop_key_val ( ) } ;
@@ -1625,11 +1632,15 @@ impl<K, V, A: Allocator> Drop for IntoIter<K, V, A> {
16251632impl < K , V , A : Allocator > IntoIter < K , V , A > {
16261633 /// Core of a `next` method returning a dying KV handle,
16271634 /// invalidated by further calls to this function and some others.
1635+ ///
1636+ /// If `root_recycling` is given some vessel, this method recycles the last
1637+ /// leaf and stores it as a fresh root in the vessel.
16281638 fn dying_next (
16291639 & mut self ,
1640+ root_recycling : Option < & mut RootVessel < K , V > > ,
16301641 ) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
16311642 if self . length == 0 {
1632- self . range . deallocating_end ( & self . alloc ) ;
1643+ self . range . deallocating_end ( & self . alloc , root_recycling ) ;
16331644 None
16341645 } else {
16351646 self . length -= 1 ;
@@ -1643,7 +1654,7 @@ impl<K, V, A: Allocator> IntoIter<K, V, A> {
16431654 & mut self ,
16441655 ) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
16451656 if self . length == 0 {
1646- self . range . deallocating_end ( & self . alloc ) ;
1657+ self . range . deallocating_end ( & self . alloc , None ) ;
16471658 None
16481659 } else {
16491660 self . length -= 1 ;
@@ -1658,7 +1669,7 @@ impl<K, V, A: Allocator> Iterator for IntoIter<K, V, A> {
16581669
16591670 fn next ( & mut self ) -> Option < ( K , V ) > {
16601671 // SAFETY: we consume the dying handle immediately.
1661- self . dying_next ( ) . map ( unsafe { |kv| kv. into_key_val ( ) } )
1672+ self . dying_next ( None ) . map ( unsafe { |kv| kv. into_key_val ( ) } )
16621673 }
16631674
16641675 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
0 commit comments