fn deallocate(mut hole: &mut Hole, addr: usize, mut size: usize) {
    loop {
        assert!(size >= HoleList::min_size());

        let hole_addr = if hole.size == 0 {
            // It's the dummy hole, which is the head of the HoleList. It's somewhere on the stack,
            // so it's address is not the address of the hole. We set the addr to 0 as it's always
            // the first hole.
            0
        } else {
            // it's a real hole in memory and its address is the address of the hole
            hole as *mut _ as usize
        };

        // Each freed block must be handled by the previous hole in memory. Thus, the freed
        // address must be always behind the current hole.
        assert!(
            hole_addr + hole.size <= addr,
            "invalid deallocation (probably a double free)"
        );

        // get information about the next block
        let next_hole_info = hole.next.as_ref().map(|next| next.info());

        match next_hole_info {
            Some(next) if hole_addr + hole.size == addr && addr + size == next.addr => {
                // block fills the gap between this hole and the next hole
                // before:  ___XXX____YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXXFFFFYYYYY____    where F is the freed block

                hole.size += size + next.size; // merge the F and Y blocks to this X block
                hole.next = hole.next.as_mut().unwrap().next.take(); // remove the Y block
            }
            _ if hole_addr + hole.size == addr => {
                // block is right behind this hole but there is used memory after it
                // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXXFFFF__YYYYY____    where F is the freed block

                // or: block is right behind this hole and this is the last hole
                // before:  ___XXX_______________    where X is this hole and Y the next hole
                // after:   ___XXXFFFF___________    where F is the freed block

                hole.size += size; // merge the F block to this X block
            }
            Some(next) if addr + size == next.addr => {
                // block is right before the next hole but there is used memory before it
                // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXX__FFFFYYYYY____    where F is the freed block

                hole.next = hole.next.as_mut().unwrap().next.take(); // remove the Y block
                size += next.size; // free the merged F/Y block in next iteration
                continue;
            }
            Some(next) if next.addr <= addr => {
                // block is behind the next hole, so we delegate it to the next hole
                // before:  ___XXX__YYYYY________    where X is this hole and Y the next hole
                // after:   ___XXX__YYYYY__FFFF__    where F is the freed block

                hole = move_helper(hole).next.as_mut().unwrap(); // start next iteration at next hole
                continue;
            }
            _ => {
                // block is between this and the next hole
                // before:  ___XXX________YYYYY_    where X is this hole and Y the next hole
                // after:   ___XXX__FFFF__YYYYY_    where F is the freed block

                // or: this is the last hole
                // before:  ___XXX_________    where X is this hole
                // after:   ___XXX__FFFF___    where F is the freed block

                let new_hole = Hole {
                    size,
                    next: hole.next.take(), // the reference to the Y block (if it exists)
                };
                // write the new hole to the freed memory
                debug_assert_eq!(addr % align_of::<Hole>(), 0);
                let ptr = addr as *mut Hole;
                unsafe { ptr.write(new_hole) };
                // add the F block as the next block of the X block
                hole.next = Some(unsafe { &mut *ptr });
            }
        }
        break;
    }
}
/// Frees the allocation given by `(addr, size)`. It starts at the given hole and walks the list to
/// find the correct place (the list is sorted by address).
Frees the allocation given by `(addr, size)`. It starts at the given hole and walks the list to
find the correct place (the list is sorted by address).
Frees the allocation given by ` ( addr size ) ` . It starts at the given hole and walks the list to find the correct place ( the list is sorted by address ) .
fn deallocate(mut hole: &mut Hole, addr: usize, mut size: usize) {
    loop {
        assert!(size >= HoleList::min_size());
        let hole_addr = if hole.size == 0 {
            // It's the dummy hole, which is the head of the HoleList. It's somewhere on the stack,
            // so it's address is not the address of the hole. We set the addr to 0 as it's always
            // the first hole.
            0
        } else {
            // it's a real hole in memory and its address is the address of the hole
            hole as *mut _ as usize
        };
        // Each freed block must be handled by the previous hole in memory. Thus, the freed
        // address must be always behind the current hole.
        assert!(
            hole_addr + hole.size <= addr,
            "invalid deallocation (probably a double free)"
        );
        // get information about the next block
        let next_hole_info = hole.next.as_ref().map(|next| next.info());
        match next_hole_info {
            Some(next) if hole_addr + hole.size == addr && addr + size == next.addr => {
                // block fills the gap between this hole and the next hole
                // before:  ___XXX____YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXXFFFFYYYYY____    where F is the freed block
                hole.size += size + next.size; // merge the F and Y blocks to this X block
                hole.next = hole.next.as_mut().unwrap().next.take(); // remove the Y block
            }
            _ if hole_addr + hole.size == addr => {
                // block is right behind this hole but there is used memory after it
                // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXXFFFF__YYYYY____    where F is the freed block
                // or: block is right behind this hole and this is the last hole
                // before:  ___XXX_______________    where X is this hole and Y the next hole
                // after:   ___XXXFFFF___________    where F is the freed block
                hole.size += size; // merge the F block to this X block
            }
            Some(next) if addr + size == next.addr => {
                // block is right before the next hole but there is used memory before it
                // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole
                // after:   ___XXX__FFFFYYYYY____    where F is the freed block
                hole.next = hole.next.as_mut().unwrap().next.take(); // remove the Y block
                size += next.size; // free the merged F/Y block in next iteration
                continue;
            }
            Some(next) if next.addr <= addr => {
                // block is behind the next hole, so we delegate it to the next hole
                // before:  ___XXX__YYYYY________    where X is this hole and Y the next hole
                // after:   ___XXX__YYYYY__FFFF__    where F is the freed block
                hole = move_helper(hole).next.as_mut().unwrap(); // start next iteration at next hole
                continue;
            }
            _ => {
                // block is between this and the next hole
                // before:  ___XXX________YYYYY_    where X is this hole and Y the next hole
                // after:   ___XXX__FFFF__YYYYY_    where F is the freed block
                // or: this is the last hole
                // before:  ___XXX_________    where X is this hole
                // after:   ___XXX__FFFF___    where F is the freed block
                let new_hole = Hole {
                    size,
                    next: hole.next.take(), // the reference to the Y block (if it exists)
                };
                // write the new hole to the freed memory
                debug_assert_eq!(addr % align_of::<Hole>(), 0);
                let ptr = addr as *mut Hole;
                unsafe { ptr.write(new_hole) };
                // add the F block as the next block of the X block
                hole.next = Some(unsafe { &mut *ptr });
            }
        }
        break;
    }
}
fn deallocate ( mut hole : & mut Hole , addr : usize , mut size : usize ) { loop { assert ! ( size HoleList min_size ( ) ) ; let hole_addr = if hole . size == 0 { // It's the dummy hole, which is the head of the HoleList. It's somewhere on the stack, // so it's address is not the address of the hole. We set the addr to 0 as it's always // the first hole. 0 } else { // it's a real hole in memory and its address is the address of the hole hole as * mut _ as usize } ; // Each freed block must be handled by the previous hole in memory. Thus, the freed // address must be always behind the current hole. assert ! ( hole_addr hole size addr " " ) ; // get information about the next block let next_hole_info = hole . next . as_ref ( ) . map ( | next | next . info ( ) ) ; match next_hole_info { Some ( next ) if hole_addr + hole . size == addr && addr + size == next . addr => { // block fills the gap between this hole and the next hole // before:  ___XXX____YYYYY____    where X is this hole and Y the next hole // after:   ___XXXFFFFYYYYY____    where F is the freed block hole . size += size + next . size ; // merge the F and Y blocks to this X block hole . next = hole . next . as_mut ( ) . unwrap ( ) . next . take ( ) ; // remove the Y block } _ if hole_addr + hole . size == addr => { // block is right behind this hole but there is used memory after it // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole // after:   ___XXXFFFF__YYYYY____    where F is the freed block // or: block is right behind this hole and this is the last hole // before:  ___XXX_______________    where X is this hole and Y the next hole // after:   ___XXXFFFF___________    where F is the freed block hole . size += size ; // merge the F block to this X block } Some ( next ) if addr + size == next . addr => { // block is right before the next hole but there is used memory before it // before:  ___XXX______YYYYY____    where X is this hole and Y the next hole // after:   ___XXX__FFFFYYYYY____    where F is the freed block hole . next = hole . next . as_mut ( ) . unwrap ( ) . next . take ( ) ; // remove the Y block size += next . size ; // free the merged F/Y block in next iteration continue ; } Some ( next ) if next . addr <= addr => { // block is behind the next hole, so we delegate it to the next hole // before:  ___XXX__YYYYY________    where X is this hole and Y the next hole // after:   ___XXX__YYYYY__FFFF__    where F is the freed block hole = move_helper ( hole ) . next . as_mut ( ) . unwrap ( ) ; // start next iteration at next hole continue ; } _ => { // block is between this and the next hole // before:  ___XXX________YYYYY_    where X is this hole and Y the next hole // after:   ___XXX__FFFF__YYYYY_    where F is the freed block // or: this is the last hole // before:  ___XXX_________    where X is this hole // after:   ___XXX__FFFF___    where F is the freed block let new_hole = Hole { size , next : hole . next . take ( ) , // the reference to the Y block (if it exists) } ; // write the new hole to the freed memory debug_assert_eq ! ( addr align_of Hole ( ) 0 ) ; let ptr = addr as * mut Hole ; unsafe { ptr . write ( new_hole ) } ; // add the F block as the next block of the X block hole . next = Some ( unsafe { & mut * ptr } ) ; } } break ; } }
Frees the allocation given by `(addr, size)`.
Frees the allocation given by ` ( addr size ) ` .
hole
&mut Hole
addr
usize
size
usize
hole
&mut Hole
addr
usize
size
usize