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