@@ -289,37 +289,76 @@ impl<BorrowType: marker::BorrowType, K, V>
289289 }
290290}
291291
292- macro_rules! def_next_kv_uncheched_dealloc {
293- { unsafe fn $name: ident : $adjacent_kv: ident } => {
294- /// Given a leaf edge handle into an owned tree, returns a handle to the next KV,
295- /// while deallocating any node left behind yet leaving the corresponding edge
296- /// in its parent node dangling.
297- ///
298- /// # Safety
299- /// - The leaf edge must not be the last one in the direction travelled.
300- /// - The node carrying the next KV returned must not have been deallocated by a
301- /// previous call on any handle obtained for this tree.
302- unsafe fn $name <K , V >(
303- leaf_edge: Handle <NodeRef <marker:: Dying , K , V , marker:: Leaf >, marker:: Edge >,
304- ) -> Handle <NodeRef <marker:: Dying , K , V , marker:: LeafOrInternal >, marker:: KV > {
305- let mut edge = leaf_edge. forget_node_type( ) ;
306- loop {
307- edge = match edge. $adjacent_kv( ) {
308- Ok ( internal_kv) => return internal_kv,
309- Err ( last_edge) => {
310- unsafe {
311- let parent_edge = last_edge. into_node( ) . deallocate_and_ascend( ) ;
312- parent_edge. unwrap_unchecked( ) . forget_node_type( )
313- }
314- }
292+ impl < K , V > Handle < NodeRef < marker:: Dying , K , V , marker:: Leaf > , marker:: Edge > {
293+ /// Given a leaf edge handle into a dying tree, returns the next leaf edge
294+ /// on the right side, and the key-value pair in between, which is either
295+ /// in the same leaf node, in an ancestor node, or non-existent.
296+ ///
297+ /// This method also deallocates any node(s) it reaches the end of. This
298+ /// implies that if no more key-value pair exists, the entire remainder of
299+ /// the tree will have been deallocated and there is nothing left to return.
300+ ///
301+ /// # Safety
302+ /// The given edge must not have been previously returned by counterpart
303+ /// `deallocating_next_back`.
304+ unsafe fn deallocating_next ( self ) -> Option < ( Self , ( K , V ) ) > {
305+ let mut edge = self . forget_node_type ( ) ;
306+ loop {
307+ edge = match edge. right_kv ( ) {
308+ Ok ( kv) => {
309+ let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
310+ let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
311+ return Some ( ( kv. next_leaf_edge ( ) , ( k, v) ) ) ;
315312 }
313+ Err ( last_edge) => match unsafe { last_edge. into_node ( ) . deallocate_and_ascend ( ) } {
314+ Some ( parent_edge) => parent_edge. forget_node_type ( ) ,
315+ None => return None ,
316+ } ,
316317 }
317318 }
318- } ;
319- }
319+ }
320320
321- def_next_kv_uncheched_dealloc ! { unsafe fn next_kv_unchecked_dealloc: right_kv}
322- def_next_kv_uncheched_dealloc ! { unsafe fn next_back_kv_unchecked_dealloc: left_kv}
321+ /// Given a leaf edge handle into a dying tree, returns the next leaf edge
322+ /// on the left side, and the key-value pair in between, which is either
323+ /// in the same leaf node, in an ancestor node, or non-existent.
324+ ///
325+ /// This method also deallocates any node(s) it reaches the end of. This
326+ /// implies that if no more key-value pair exists, the entire remainder of
327+ /// the tree will have been deallocated and there is nothing left to return.
328+ ///
329+ /// # Safety
330+ /// The given edge must not have been previously returned by counterpart
331+ /// `deallocating_next`.
332+ unsafe fn deallocating_next_back ( self ) -> Option < ( Self , ( K , V ) ) > {
333+ let mut edge = self . forget_node_type ( ) ;
334+ loop {
335+ edge = match edge. left_kv ( ) {
336+ Ok ( kv) => {
337+ let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
338+ let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
339+ return Some ( ( kv. next_back_leaf_edge ( ) , ( k, v) ) ) ;
340+ }
341+ Err ( last_edge) => match unsafe { last_edge. into_node ( ) . deallocate_and_ascend ( ) } {
342+ Some ( parent_edge) => parent_edge. forget_node_type ( ) ,
343+ None => return None ,
344+ } ,
345+ }
346+ }
347+ }
348+
349+ /// Deallocates a pile of nodes from the leaf up to the root.
350+ /// This is the only way to deallocate the remainder of a tree after
351+ /// `deallocating_next` and `deallocating_next_back` have been nibbling at
352+ /// both sides of the tree, and have hit the same edge. As it is intended
353+ /// only to be called when all keys and values have been returned,
354+ /// no cleanup is done on any of the keys or values.
355+ pub fn deallocating_end ( self ) {
356+ let mut edge = self . forget_node_type ( ) ;
357+ while let Some ( parent_edge) = unsafe { edge. into_node ( ) . deallocate_and_ascend ( ) } {
358+ edge = parent_edge. forget_node_type ( ) ;
359+ }
360+ }
361+ }
323362
324363impl < ' a , K , V > Handle < NodeRef < marker:: Immut < ' a > , K , V , marker:: Leaf > , marker:: Edge > {
325364 /// Moves the leaf edge handle to the next leaf edge and returns references to the
@@ -394,12 +433,9 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
394433 /// The only safe way to proceed with the updated handle is to compare it, drop it,
395434 /// call this method again subject to its safety conditions, or call counterpart
396435 /// `next_back_unchecked` subject to its safety conditions.
397- pub unsafe fn next_unchecked ( & mut self ) -> ( K , V ) {
398- super :: mem:: replace ( self , |leaf_edge| {
399- let kv = unsafe { next_kv_unchecked_dealloc ( leaf_edge) } ;
400- let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
401- let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
402- ( kv. next_leaf_edge ( ) , ( k, v) )
436+ pub unsafe fn deallocating_next_unchecked ( & mut self ) -> ( K , V ) {
437+ super :: mem:: replace ( self , |leaf_edge| unsafe {
438+ leaf_edge. deallocating_next ( ) . unwrap_unchecked ( )
403439 } )
404440 }
405441
@@ -415,12 +451,9 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
415451 /// The only safe way to proceed with the updated handle is to compare it, drop it,
416452 /// call this method again subject to its safety conditions, or call counterpart
417453 /// `next_unchecked` subject to its safety conditions.
418- pub unsafe fn next_back_unchecked ( & mut self ) -> ( K , V ) {
419- super :: mem:: replace ( self , |leaf_edge| {
420- let kv = unsafe { next_back_kv_unchecked_dealloc ( leaf_edge) } ;
421- let k = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 0 ) } ;
422- let v = unsafe { ptr:: read ( kv. reborrow ( ) . into_kv ( ) . 1 ) } ;
423- ( kv. next_back_leaf_edge ( ) , ( k, v) )
454+ pub unsafe fn deallocating_next_back_unchecked ( & mut self ) -> ( K , V ) {
455+ super :: mem:: replace ( self , |leaf_edge| unsafe {
456+ leaf_edge. deallocating_next_back ( ) . unwrap_unchecked ( )
424457 } )
425458 }
426459}
0 commit comments