@@ -289,37 +289,76 @@ impl<BorrowType: marker::BorrowType, K, V>
289
289
}
290
290
}
291
291
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) ) ) ;
315
312
}
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
+ } ,
316
317
}
317
318
}
318
- } ;
319
- }
319
+ }
320
320
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
+ }
323
362
324
363
impl < ' a , K , V > Handle < NodeRef < marker:: Immut < ' a > , K , V , marker:: Leaf > , marker:: Edge > {
325
364
/// 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> {
394
433
/// The only safe way to proceed with the updated handle is to compare it, drop it,
395
434
/// call this method again subject to its safety conditions, or call counterpart
396
435
/// `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 ( )
403
439
} )
404
440
}
405
441
@@ -415,12 +451,9 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
415
451
/// The only safe way to proceed with the updated handle is to compare it, drop it,
416
452
/// call this method again subject to its safety conditions, or call counterpart
417
453
/// `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 ( )
424
457
} )
425
458
}
426
459
}
0 commit comments