11use  core:: alloc:: Layout ; 
2- use  core:: convert:: { TryFrom ,   TryInto } ; 
2+ use  core:: convert:: TryInto ; 
33use  core:: mem; 
44use  core:: mem:: { align_of,  size_of} ; 
55use  core:: ptr:: NonNull ; 
@@ -13,42 +13,20 @@ pub struct HoleList {
1313    pub ( crate )  first :  Hole ,  // dummy 
1414} 
1515
16- pub  struct  Cursor  { 
16+ pub ( crate )  struct  Cursor  { 
1717    prev :  NonNull < Hole > , 
1818    hole :  NonNull < Hole > , 
1919} 
2020
21- enum  Position < ' a >  { 
22-     BeforeCurrent , 
23-     BetweenCurrentNext  { 
24-         curr :  & ' a  Hole , 
25-         next :  & ' a  Hole , 
26-     } , 
27-     AfterBoth , 
28-     AfterCurrentNoNext , 
29- } 
30- 
3121impl  Cursor  { 
3222    fn  next ( mut  self )  -> Option < Self >  { 
3323        unsafe  { 
34-             if   let   Some ( nhole )  =  self . hole . as_mut ( ) . next  { 
35-                 Some ( Cursor  { 
24+             self . hole . as_mut ( ) . next . map ( |nhole|  { 
25+                 Cursor  { 
3626                    prev :  self . hole , 
3727                    hole :  nhole, 
38-                 } ) 
39-             }  else  { 
40-                 None 
41-             } 
42-         } 
43-     } 
44- 
45-     fn  peek_next ( & self )  -> Option < & Hole >  { 
46-         unsafe  { 
47-             if  let  Some ( nhole)  = self . hole . as_ref ( ) . next  { 
48-                 Some ( nhole. as_ref ( ) ) 
49-             }  else  { 
50-                 None 
51-             } 
28+                 } 
29+             } ) 
5230        } 
5331    } 
5432
@@ -170,7 +148,6 @@ impl Cursor {
170148
171149        // As of now, the old `Hole` is no more. We are about to replace it with one or more of 
172150        // the front padding, the allocation, and the back padding. 
173-         drop ( hole) ; 
174151
175152        match  ( front_padding,  back_padding)  { 
176153            ( None ,  None )  => { 
@@ -249,7 +226,7 @@ impl HoleList {
249226        } 
250227    } 
251228
252-     pub  fn  cursor ( & mut  self )  -> Option < Cursor >  { 
229+     pub ( crate )  fn  cursor ( & mut  self )  -> Option < Cursor >  { 
253230        if  let  Some ( hole)  = self . first . next  { 
254231            Some ( Cursor  { 
255232                hole, 
@@ -326,9 +303,7 @@ impl HoleList {
326303            size = Self :: min_size ( ) ; 
327304        } 
328305        let  size = align_up_size ( size,  mem:: align_of :: < Hole > ( ) ) ; 
329-         let  layout = Layout :: from_size_align ( size,  layout. align ( ) ) . unwrap ( ) ; 
330- 
331-         layout
306+         Layout :: from_size_align ( size,  layout. align ( ) ) . unwrap ( ) 
332307    } 
333308
334309    /// Searches the list for a big enough hole. 
@@ -396,35 +371,13 @@ pub(crate) struct Hole {
396371    pub  next :  Option < NonNull < Hole > > , 
397372} 
398373
399- impl  Hole  { 
400-     /// Returns basic information about the hole. 
401-      fn  info ( & mut  self )  -> HoleInfo  { 
402-         HoleInfo  { 
403-             addr :  self  as  * mut  _  as  * mut  u8 , 
404-             size :  self . size , 
405-         } 
406-     } 
407- 
408-     fn  addr_u8 ( & self )  -> * const  u8  { 
409-         self  as  * const  Hole  as  * const  u8 
410-     } 
411- } 
412- 
413374/// Basic information about a hole. 
414375#[ derive( Debug ,  Clone ,  Copy ) ]  
415376struct  HoleInfo  { 
416377    addr :  * mut  u8 , 
417378    size :  usize , 
418379} 
419380
420- /// The result returned by `split_hole` and `allocate_first_fit`. Contains the address and size of 
421- /// the allocation (in the `info` field), and the front and back padding. 
422- struct  Allocation  { 
423-     info :  HoleInfo , 
424-     front_padding :  Option < HoleInfo > , 
425-     back_padding :  Option < HoleInfo > , 
426- } 
427- 
428381unsafe  fn  make_hole ( addr :  * mut  u8 ,  size :  usize )  -> NonNull < Hole >  { 
429382    let  hole_addr = addr. cast :: < Hole > ( ) ; 
430383    debug_assert_eq ! ( addr as  usize  % align_of:: <Hole >( ) ,  0 ) ; 
@@ -482,12 +435,11 @@ impl Cursor {
482435        } 
483436    } 
484437
485- 
486-     // Merge the current node with an IMMEDIATELY FOLLOWING next node 
487-     fn  try_merge_next_two ( self )  { 
438+     // Merge the current node with up to n following nodes 
439+     fn  try_merge_next_n ( self ,  max :  usize )  { 
488440        let  Cursor  {  prev :  _,  mut  hole }  = self ; 
489441
490-         for  _ in  0 ..2  { 
442+         for  _ in  0 ..max  { 
491443            // Is there a next node? 
492444            let  mut  next = if  let  Some ( next)  = unsafe  {  hole. as_mut ( )  } . next . as_ref ( )  { 
493445                * next
@@ -496,13 +448,12 @@ impl Cursor {
496448            } ; 
497449
498450            // Can we directly merge these? e.g. are they touching? 
499-             // 
500-             // TODO(AJM): Should "touching" also include deltas <= node size? 
501451            let  hole_u8 = hole. as_ptr ( ) . cast :: < u8 > ( ) ; 
502452            let  hole_sz = unsafe  {  hole. as_ref ( ) . size  } ; 
503453            let  next_u8 = next. as_ptr ( ) . cast :: < u8 > ( ) ; 
454+             let  end = hole_u8. wrapping_add ( hole_sz) ; 
504455
505-             let  touching = hole_u8 . wrapping_add ( hole_sz )  == next_u8; 
456+             let  touching = end  == next_u8; 
506457
507458            if  touching { 
508459                let  next_sz; 
@@ -531,56 +482,55 @@ impl Cursor {
531482/// Frees the allocation given by `(addr, size)`. It starts at the given hole and walks the list to 
532483/// find the correct place (the list is sorted by address). 
533484fn  deallocate ( list :  & mut  HoleList ,  addr :  * mut  u8 ,  size :  usize )  { 
534-     // Start off by just making this allocation a hole. 
485+     // Start off by just making this allocation a hole where it stands. 
486+     // We'll attempt to merge it with other nodes once we figure out where 
487+     // it should live 
535488    let  hole = unsafe  {  make_hole ( addr,  size)  } ; 
536489
490+     // Now, try to get a cursor to the list - this only works if we have at least 
491+     // one non-"dummy" hole in the list 
537492    let  cursor = if  let  Some ( cursor)  = list. cursor ( )  { 
538493        cursor
539494    }  else  { 
540-         // Oh hey, there are no holes at all. That means this just becomes the only hole! 
495+         // Oh hey, there are no "real" holes at all. That means this just 
496+         // becomes the only "real" hole! 
541497        list. first . next  = Some ( hole) ; 
542498        return ; 
543499    } ; 
544500
545501    // First, check if we can just insert this node at the top of the list. If the 
546502    // insertion succeeded, then our cursor now points to the NEW node, behind the 
547503    // previous location the cursor was pointing to. 
548-     let  cursor = match  cursor. try_insert_back ( hole)  { 
504+     // 
505+     // Otherwise, our cursor will point at the current non-"dummy" head of the list 
506+     let  ( cursor,  n)  = match  cursor. try_insert_back ( hole)  { 
549507        Ok ( cursor)  => { 
550-             // Yup! It lives at the front of the list. Hooray! 
551-             cursor
508+             // Yup! It lives at the front of the list. Hooray! Attempt to merge 
509+             // it with just ONE next node, since it is at the front of the list 
510+             ( cursor,  1 ) 
552511        } , 
553512        Err ( mut  cursor)  => { 
554513            // Nope. It lives somewhere else. Advance the list until we find its home 
555514            while  let  Err ( ( ) )  = cursor. try_insert_after ( hole)  { 
556515                cursor = cursor. next ( ) . unwrap ( ) ; 
557516            } 
558-             cursor
517+             // Great! We found a home for it, our cursor is now JUST BEFORE the new 
518+             // node we inserted, so we need to try to merge up to twice: One to combine 
519+             // the current node to the new node, then once more to combine the new node 
520+             // with the node after that. 
521+             ( cursor,  2 ) 
559522        } , 
560523    } ; 
561524
562525    // We now need to merge up to two times to combine the current node with the next 
563526    // two nodes. 
564-     cursor. try_merge_next_two ( ) ; 
565- } 
566- 
567- 
568- /// Identity function to ease moving of references. 
569- /// 
570- /// By default, references are reborrowed instead of moved (equivalent to `&mut *reference`). This 
571- /// function forces a move. 
572- /// 
573- /// for more information, see section “id Forces References To Move” in: 
574- /// https://bluss.github.io/rust/fun/2015/10/11/stuff-the-identity-function-does/ 
575- fn  move_helper < T > ( x :  T )  -> T  { 
576-     x
527+     cursor. try_merge_next_n ( n) ; 
577528} 
578529
579530#[ cfg( test) ]  
580531pub  mod  test { 
581-     use  super :: * ; 
582532    use  core:: alloc:: Layout ; 
583-     use  std:: mem:: { align_of ,  size_of ,   MaybeUninit } ; 
533+     use  std:: mem:: MaybeUninit ; 
584534    use  std:: prelude:: v1:: * ; 
585535    use  crate :: Heap ; 
586536
@@ -612,16 +562,13 @@ pub mod test {
612562    #[ test]  
613563    fn  cursor ( )  { 
614564        let  mut  heap = new_heap ( ) ; 
615-         let  curs = heap. holes_mut ( ) . cursor ( ) . unwrap ( ) ; 
565+         let  curs = heap. holes . cursor ( ) . unwrap ( ) ; 
616566        // This is the "dummy" node 
617567        assert_eq ! ( curs. previous( ) . size,  0 ) ; 
618568        // This is the "full" heap 
619569        assert_eq ! ( curs. current( ) . size,  1000 ) ; 
620570        // There is no other hole 
621-         assert ! ( curs. peek_next( ) . is_none( ) ) ; 
622- 
623-         let  reqd = Layout :: from_size_align ( 256 ,  1 ) . unwrap ( ) ; 
624-         let  _ = curs. split_current ( reqd) . map_err ( drop) . unwrap ( ) ; 
571+         assert ! ( curs. next( ) . is_none( ) ) ; 
625572    } 
626573
627574    #[ test]  
0 commit comments