diff --git a/src/pdata/space_map.rs b/src/pdata/space_map.rs
index 7c138bf..da80f7b 100644
--- a/src/pdata/space_map.rs
+++ b/src/pdata/space_map.rs
@@ -24,9 +24,16 @@ pub trait SpaceMap {
Ok(old == 1)
}
- /// Finds a block with a zero reference count. Increments the
- /// count.
+ /// Finds a block with a zero reference count. Increments the count.
+ /// Returns Ok(None) if no free block (ENOSPC)
+ /// Returns Err on fatal error
fn alloc(&mut self) -> Result>;
+
+ /// Finds a free block within the range
+ fn find_free(&mut self, begin: u64, end: u64) -> Result >;
+
+ /// Returns the position where allocation starts
+ fn get_alloc_begin(&self) -> Result;
}
pub type ASpaceMap = Arc>;
@@ -35,7 +42,7 @@ pub type ASpaceMap = Arc>;
pub struct CoreSpaceMap {
nr_allocated: u64,
- first_free: u64,
+ alloc_begin: u64,
counts: Vec,
}
@@ -46,7 +53,7 @@ where
pub fn new(nr_entries: u64) -> CoreSpaceMap {
CoreSpaceMap {
nr_allocated: 0,
- first_free: 0,
+ alloc_begin: 0,
counts: vec![V::default(); nr_entries as usize],
}
}
@@ -77,9 +84,6 @@ where
self.nr_allocated += 1;
} else if old != V::from(0u8) && v == 0 {
self.nr_allocated -= 1;
- if b < self.first_free {
- self.first_free = b;
- }
}
Ok(old.into())
@@ -99,18 +103,33 @@ where
}
fn alloc(&mut self) -> Result> {
- for b in self.first_free..(self.counts.len() as u64) {
- if self.counts[b as usize] == V::from(0u8) {
- self.counts[b as usize] = V::from(1u8);
- self.first_free = b + 1;
- self.nr_allocated += 1;
- return Ok(Some(b));
+ let mut b = self.find_free(self.alloc_begin, self.counts.len() as u64)?;
+ if b.is_none() {
+ b = self.find_free(0, self.alloc_begin)?;
+ if b.is_none() {
+ return Ok(None);
}
}
- self.first_free = self.counts.len() as u64;
+ self.counts[b.unwrap() as usize] = V::from(1u8);
+ self.nr_allocated += 1;
+ self.alloc_begin = b.unwrap() + 1;
+
+ Ok(b)
+ }
+
+ fn find_free(&mut self, begin: u64, end: u64) -> Result > {
+ for b in begin..end {
+ if self.counts[b as usize] == V::from(0u8) {
+ return Ok(Some(b));
+ }
+ }
Ok(None)
}
+
+ fn get_alloc_begin(&self) -> Result {
+ Ok(self.alloc_begin as u64)
+ }
}
pub fn core_sm(nr_entries: u64, max_count: u32) -> Arc> {
@@ -150,7 +169,7 @@ pub fn clone_space_map(src: &dyn SpaceMap) -> Result> {
// aren't interested in counting how many times we've visited.
pub struct RestrictedSpaceMap {
nr_allocated: u64,
- first_free: usize,
+ alloc_begin: usize,
counts: FixedBitSet,
}
@@ -159,7 +178,7 @@ impl RestrictedSpaceMap {
RestrictedSpaceMap {
nr_allocated: 0,
counts: FixedBitSet::with_capacity(nr_entries as usize),
- first_free: 0,
+ alloc_begin: 0,
}
}
}
@@ -192,9 +211,6 @@ impl SpaceMap for RestrictedSpaceMap {
} else {
if old {
self.nr_allocated -= 1;
- if b < self.first_free as u64 {
- self.first_free = b as usize;
- }
}
self.counts.set(b as usize, false);
}
@@ -213,17 +229,33 @@ impl SpaceMap for RestrictedSpaceMap {
}
fn alloc(&mut self) -> Result> {
- for b in self.first_free..self.counts.len() {
- if !self.counts.contains(b) {
- self.counts.insert(b);
- self.first_free = b + 1;
- return Ok(Some(b as u64));
+ let mut b = self.find_free(self.alloc_begin as u64, self.counts.len() as u64)?;
+ if b.is_none() {
+ b = self.find_free(0, self.alloc_begin as u64)?;
+ if b.is_none() {
+ return Ok(None);
}
}
- self.first_free = self.counts.len();
+ self.counts.insert(b.unwrap() as usize);
+ self.nr_allocated += 1;
+ self.alloc_begin = b.unwrap() as usize + 1;
+
+ Ok(b)
+ }
+
+ fn find_free(&mut self, begin: u64, end: u64) -> Result > {
+ for b in begin..end {
+ if !self.counts.contains(b as usize) {
+ return Ok(Some(b));
+ }
+ }
Ok(None)
}
+
+ fn get_alloc_begin(&self) -> Result {
+ Ok(self.alloc_begin as u64)
+ }
}
//------------------------------------------