diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d058f09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +target/ +.*/ +!.github + +# https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 6f153ed..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,16 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "bit_field" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitmap-allocator" -version = "0.1.0" -dependencies = [ - "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" diff --git a/Cargo.toml b/Cargo.toml index d0495fd..9025621 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,8 @@ name = "bitmap-allocator" version = "0.1.0" authors = ["WangRunji "] -edition = "2018" +edition = "2021" +readme = "README.md" [dependencies] -bit_field = "0.9" +bit_field = "0.10" diff --git a/README.md b/README.md index fab083e..936309e 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ [![CI](https://github.com/rcore-os/bitmap-allocator/workflows/CI/badge.svg?branch=master)](https://github.com/rcore-os/bitmap-allocator/actions) [![Coverage Status](https://coveralls.io/repos/github/rcore-os/bitmap-allocator/badge.svg?branch=master)](https://coveralls.io/github/rcore-os/bitmap-allocator?branch=master) + +Bit allocator based on segment tree algorithm. diff --git a/src/lib.rs b/src/lib.rs index 7784641..a3c5278 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +//! Bit allocator based on segment tree algorithm. + #![no_std] use bit_field::BitField; @@ -9,7 +11,6 @@ pub trait BitAlloc: Default { const CAP: usize; /// The default value. Workaround for `const fn new() -> Self`. - #[allow(clippy::declare_interior_mutable_const)] const DEFAULT: Self; /// Allocate a free bit. @@ -31,8 +32,12 @@ pub trait BitAlloc: Default { fn remove(&mut self, range: Range); /// Whether there are free bits remaining + #[deprecated = "use `!self.is_empty()` instead"] fn any(&self) -> bool; + /// Returns true if no bits is available. + fn is_empty(&self) -> bool; + /// Whether a specific bit is free fn test(&self, key: usize) -> bool; } @@ -66,10 +71,10 @@ impl BitAlloc for BitAllocCascade16 { }; fn alloc(&mut self) -> Option { - if self.any() { + if !self.is_empty() { let i = self.bitset.trailing_zeros() as usize; let res = self.sub[i].alloc().unwrap() + i * T::CAP; - self.bitset.set_bit(i, self.sub[i].any()); + self.bitset.set_bit(i, !self.sub[i].is_empty()); Some(res) } else { None @@ -95,7 +100,10 @@ impl BitAlloc for BitAllocCascade16 { self.for_range(range, |sub: &mut T, range| sub.remove(range)); } fn any(&self) -> bool { - self.bitset != 0 + !self.is_empty() + } + fn is_empty(&self) -> bool { + self.bitset == 0 } fn test(&self, key: usize) -> bool { self.sub[key / T::CAP].test(key % T::CAP) @@ -130,25 +138,24 @@ impl BitAllocCascade16 { T::CAP }; f(&mut self.sub[i], begin..end); - self.bitset.set_bit(i, self.sub[i].any()); + self.bitset.set_bit(i, !self.sub[i].is_empty()); } } } /// A bitmap consisting of only 16 bits. -/// BitAlloc16 acts as the leaf (except the leaf bits of course) nodes -/// in the segment trees. +/// BitAlloc16 acts as the leaf (except the leaf bits of course) nodes in the segment trees. #[derive(Default)] pub struct BitAlloc16(u16); impl BitAlloc for BitAlloc16 { - const CAP: usize = 16; + const CAP: usize = u16::BITS as usize; - const DEFAULT: Self = BitAlloc16(0); + const DEFAULT: Self = Self(0); fn alloc(&mut self) -> Option { - if self.any() { - let i = self.0.trailing_zeros() as usize; + let i = self.0.trailing_zeros() as usize; + if i < Self::CAP { self.0.set_bit(i, false); Some(i) } else { @@ -174,13 +181,16 @@ impl BitAlloc for BitAlloc16 { self.0.set_bits(range, 0); } fn any(&self) -> bool { - self.0 != 0 + !self.is_empty() + } + fn is_empty(&self) -> bool { + self.0 == 0 } fn test(&self, key: usize) -> bool { self.0.get_bit(key) } fn next(&self, key: usize) -> Option { - (key..16).find(|&i| self.0.get_bit(i)) + (key..Self::CAP).find(|&i| self.0.get_bit(i)) } } @@ -190,7 +200,7 @@ fn find_contiguous( size: usize, align_log2: usize, ) -> Option { - if capacity < (1 << align_log2) || !ba.any() { + if capacity < (1 << align_log2) || ba.is_empty() { return None; } let mut base = 0; @@ -227,7 +237,7 @@ mod tests { assert_eq!(BitAlloc16::CAP, 16); ba.insert(0..16); for i in 0..16 { - assert_eq!(ba.test(i), true); + assert!(ba.test(i)); } ba.remove(2..8); assert_eq!(ba.alloc(), Some(0)); @@ -237,10 +247,11 @@ mod tests { ba.dealloc(1); ba.dealloc(8); + assert!(!ba.is_empty()); for _ in 0..10 { assert!(ba.alloc().is_some()); } - assert!(!ba.any()); + assert!(ba.is_empty()); assert!(ba.alloc().is_none()); } @@ -250,11 +261,11 @@ mod tests { assert_eq!(BitAlloc4K::CAP, 4096); ba.insert(0..4096); for i in 0..4096 { - assert_eq!(ba.test(i), true); + assert!(ba.test(i)); } ba.remove(2..4094); for i in 0..4096 { - assert_eq!(ba.test(i), i < 2 || i >= 4094); + assert_eq!(ba.test(i), !(2..4094).contains(&i)); } assert_eq!(ba.alloc(), Some(0)); assert_eq!(ba.alloc(), Some(1)); @@ -263,9 +274,11 @@ mod tests { ba.dealloc(1); ba.dealloc(4094); + assert!(!ba.is_empty()); for _ in 0..4 { assert!(ba.alloc().is_some()); } + assert!(ba.is_empty()); assert!(ba.alloc().is_none()); }