@@ -13,7 +13,7 @@ use crate::alloc::{Allocator, Global};
13
13
14
14
use super :: borrow:: DormantMutRef ;
15
15
use super :: dedup_sorted_iter:: DedupSortedIter ;
16
- use super :: navigate:: { LazyLeafRange , LeafRange } ;
16
+ use super :: navigate:: { LazyLeafRange , LeafRange , RootVessel } ;
17
17
use super :: node:: { self , marker, ForceResult :: * , Handle , NodeRef , Root } ;
18
18
use super :: search:: SearchResult :: * ;
19
19
@@ -559,6 +559,7 @@ impl<K, V> BTreeMap<K, V> {
559
559
560
560
impl < K , V , A : Allocator > BTreeMap < K , V , A > {
561
561
/// Clears the map, removing all elements.
562
+ /// Keeps a part of the allocated memory for reuse.
562
563
///
563
564
/// # Examples
564
565
///
@@ -574,12 +575,18 @@ impl<K, V, A: Allocator> BTreeMap<K, V, A> {
574
575
/// ```
575
576
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
576
577
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
+ }
583
590
}
584
591
585
592
/// 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> {
1606
1613
fn drop ( & mut self ) {
1607
1614
// Continue the same loop we perform below. This only runs when unwinding, so we
1608
1615
// 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 ) {
1610
1617
// SAFETY: we consume the dying handle immediately.
1611
1618
unsafe { kv. drop_key_val ( ) } ;
1612
1619
}
1613
1620
}
1614
1621
}
1615
1622
1616
- while let Some ( kv) = self . dying_next ( ) {
1623
+ while let Some ( kv) = self . dying_next ( None ) {
1617
1624
let guard = DropGuard ( self ) ;
1618
1625
// SAFETY: we don't touch the tree before consuming the dying handle.
1619
1626
unsafe { kv. drop_key_val ( ) } ;
@@ -1625,11 +1632,15 @@ impl<K, V, A: Allocator> Drop for IntoIter<K, V, A> {
1625
1632
impl < K , V , A : Allocator > IntoIter < K , V , A > {
1626
1633
/// Core of a `next` method returning a dying KV handle,
1627
1634
/// 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.
1628
1638
fn dying_next (
1629
1639
& mut self ,
1640
+ root_recycling : Option < & mut RootVessel < K , V > > ,
1630
1641
) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
1631
1642
if self . length == 0 {
1632
- self . range . deallocating_end ( & self . alloc ) ;
1643
+ self . range . deallocating_end ( & self . alloc , root_recycling ) ;
1633
1644
None
1634
1645
} else {
1635
1646
self . length -= 1 ;
@@ -1643,7 +1654,7 @@ impl<K, V, A: Allocator> IntoIter<K, V, A> {
1643
1654
& mut self ,
1644
1655
) -> Option < Handle < NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > , marker:: KV > > {
1645
1656
if self . length == 0 {
1646
- self . range . deallocating_end ( & self . alloc ) ;
1657
+ self . range . deallocating_end ( & self . alloc , None ) ;
1647
1658
None
1648
1659
} else {
1649
1660
self . length -= 1 ;
@@ -1658,7 +1669,7 @@ impl<K, V, A: Allocator> Iterator for IntoIter<K, V, A> {
1658
1669
1659
1670
fn next ( & mut self ) -> Option < ( K , V ) > {
1660
1671
// 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 ( ) } )
1662
1673
}
1663
1674
1664
1675
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
0 commit comments