pub struct RangeAllocator<T> { /* private fields */ }Expand description
A best-fit range allocator over a generic index type T.
RangeAllocator manages a single contiguous range and hands out
non-overlapping sub-ranges on request. Freed ranges are automatically
merged with their neighbors.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..100);
let r = alloc.allocate_range(10).unwrap();
assert_eq!(r, 0..10);
alloc.free_range(r);Implementations§
Source§impl<T> RangeAllocator<T>
impl<T> RangeAllocator<T>
Sourcepub fn new(range: Range<T>) -> Self
pub fn new(range: Range<T>) -> Self
Creates a new allocator that manages the given range.
The entire range starts as free and available for allocation.
§Example
use range_alloc::RangeAllocator;
let alloc = RangeAllocator::new(0u32..1024);
assert!(alloc.is_empty());Sourcepub fn initial_range(&self) -> &Range<T>
pub fn initial_range(&self) -> &Range<T>
Returns the full range this allocator was created with
(including any extensions from grow_to).
Sourcepub fn grow_to(&mut self, new_end: T)
pub fn grow_to(&mut self, new_end: T)
Extends the allocator’s range to a new end value.
The newly added region (old_end..new_end) becomes available for
allocation. If the last free range is adjacent to the old end, it
is extended in place rather than creating a new entry.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..10);
alloc.allocate_range(10).unwrap();
// Out of space -- grow the pool.
alloc.grow_to(20);
let r = alloc.allocate_range(5).unwrap();
assert_eq!(r, 10..15);Sourcepub fn allocate_range(
&mut self,
length: T,
) -> Result<Range<T>, RangeAllocationError<T>>
pub fn allocate_range( &mut self, length: T, ) -> Result<Range<T>, RangeAllocationError<T>>
Allocates a sub-range of the given length.
Uses a best-fit strategy: the smallest free range that can satisfy the request is chosen to minimise fragmentation.
§Panics
Panics if length is zero.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..100);
let a = alloc.allocate_range(30).unwrap();
let b = alloc.allocate_range(20).unwrap();
assert_eq!(a, 0..30);
assert_eq!(b, 30..50);Sourcepub fn allocate_range_aligned(
&mut self,
length: T,
alignment: T,
) -> Result<Range<T>, RangeAllocationError<T>>where
T: Rem<Output = T>,
pub fn allocate_range_aligned(
&mut self,
length: T,
alignment: T,
) -> Result<Range<T>, RangeAllocationError<T>>where
T: Rem<Output = T>,
Allocates a sub-range of the given length whose start is aligned
to a multiple of alignment.
Any space before the aligned start within a free range is kept free and available for future allocations – no space is wasted on alignment padding.
Uses the same best-fit strategy as allocate_range.
§Panics
Panics if length or alignment is zero.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..256);
// Offset the free region so the next aligned start is not at 0.
alloc.allocate_range(1).unwrap(); // 0..1
// Allocate 16 units starting at the next multiple of 16.
let r = alloc.allocate_range_aligned(16, 16).unwrap();
assert_eq!(r, 16..32);
// The gap (1..16) is still free and usable.
let small = alloc.allocate_range(15).unwrap();
assert_eq!(small, 1..16);Sourcepub fn free_range(&mut self, range: Range<T>)
pub fn free_range(&mut self, range: Range<T>)
Returns a previously allocated range to the free pool.
Adjacent free ranges are automatically merged to reduce fragmentation.
§Panics
Panics if range is outside the allocator’s initial range, is
empty, or overlaps with an already-free range.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..10);
let r = alloc.allocate_range(10).unwrap();
alloc.free_range(r);
assert!(alloc.is_empty());Sourcepub fn allocated_ranges(&self) -> impl Iterator<Item = Range<T>> + '_
pub fn allocated_ranges(&self) -> impl Iterator<Item = Range<T>> + '_
Returns an iterator over all currently allocated (non-free) ranges.
The ranges are yielded in ascending order.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..30);
alloc.allocate_range(10).unwrap(); // 0..10
alloc.allocate_range(10).unwrap(); // 10..20
// Adjacent allocations appear as a single contiguous range.
let allocated: Vec<_> = alloc.allocated_ranges().collect();
assert_eq!(allocated, vec![0..20]);Source§impl<T: Copy + Sub<Output = T> + Sum> RangeAllocator<T>
impl<T: Copy + Sub<Output = T> + Sum> RangeAllocator<T>
Sourcepub fn total_available(&self) -> T
pub fn total_available(&self) -> T
Returns the total length of all free ranges combined.
This may be spread across multiple non-contiguous ranges, so an allocation of this size is not guaranteed to succeed.
§Example
use range_alloc::RangeAllocator;
let mut alloc = RangeAllocator::new(0..100);
alloc.allocate_range(30).unwrap();
assert_eq!(alloc.total_available(), 70);