diff --git a/src/lib.rs b/src/lib.rs index 1dcb781..416ac3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ //! //! // Allocate a buffer with capacity 1024. //! let mut buf = pool.alloc(1024); +//! buf.resize(1024, 0); //! //! // write some data into it //! for i in 0..100 { diff --git a/src/pool.rs b/src/pool.rs index 05e413e..8ab95cd 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -90,7 +90,8 @@ impl BytePool { impl<'a, T: Poolable> Drop for Block<'a, T> { fn drop(&mut self) { - let data = mem::ManuallyDrop::into_inner(unsafe { ptr::read(&self.data) }); + let mut data = mem::ManuallyDrop::into_inner(unsafe { ptr::read(&self.data) }); + data.reset(); self.pool.push_raw_block(data); } } @@ -138,6 +139,20 @@ unsafe impl<'a, T: StableDeref + Poolable> StableDeref for Block<'a, T> {} #[cfg(test)] mod tests { use super::*; + #[test] + fn append() { + let pool = BytePool::>::new(); + let mut buf = pool.alloc(4); + assert_eq!(0, buf.len()); + assert_eq!(4, buf.capacity()); + buf.push(12u8); + assert_eq!(1, buf.len()); + buf.extend_from_slice("hello".as_bytes()); + assert_eq!(6, buf.len()); + buf.clear(); + assert_eq!(0, buf.len()); + assert!(buf.capacity() > 0); + } #[test] fn basics_vec_u8() { @@ -174,6 +189,7 @@ mod tests { let _slice: &[u8] = &buf; assert_eq!(buf.capacity(), 10); + buf.resize(10, 0); for i in 0..10 { buf[i] = 1; } @@ -199,7 +215,7 @@ mod tests { let h1 = std::thread::spawn(move || { for _ in 0..100 { let mut buf = pool1.alloc(64); - buf[10] = 10; + buf.push(10); } }); @@ -207,7 +223,7 @@ mod tests { let h2 = std::thread::spawn(move || { for _ in 0..100 { let mut buf = pool2.alloc(64); - buf[10] = 10; + buf.push(10); } }); diff --git a/src/poolable.rs b/src/poolable.rs index 23fd0cc..14fb143 100644 --- a/src/poolable.rs +++ b/src/poolable.rs @@ -3,17 +3,32 @@ use std::hash::{BuildHasher, Hash}; /// The trait required to be able to use a type in `BytePool`. pub trait Poolable { + fn empty(&self) -> bool; + fn len(&self) -> usize; fn capacity(&self) -> usize; fn alloc(size: usize) -> Self; + fn reset(&mut self); } impl Poolable for Vec { - fn capacity(&self) -> usize { + fn empty(&self) -> bool { + self.len() == 0 + } + + fn len(&self) -> usize { self.len() } + fn capacity(&self) -> usize { + self.capacity() + } + fn alloc(size: usize) -> Self { - vec![T::default(); size] + Vec::::with_capacity(size) + } + + fn reset(&mut self) { + self.clear(); } } @@ -22,13 +37,25 @@ where K: Eq + Hash, S: BuildHasher + Default, { - fn capacity(&self) -> usize { + fn empty(&self) -> bool { + self.len() == 0 + } + + fn len(&self) -> usize { self.len() } + fn capacity(&self) -> usize { + self.capacity() + } + fn alloc(size: usize) -> Self { HashMap::with_capacity_and_hasher(size, Default::default()) } + + fn reset(&mut self) { + self.clear(); + } } /// A trait allowing for efficient reallocation. @@ -42,7 +69,7 @@ impl Realloc for Vec { assert!(new_size > 0); match new_size.cmp(&self.capacity()) { - Greater => self.resize(new_size, T::default()), + Greater => self.reserve(new_size - self.capacity()), Less => { self.truncate(new_size); self.shrink_to_fit();