Skip to content

Commit e3a193a

Browse files
committed
ensure len and capacity methods reflect their intentions
1 parent 2a50848 commit e3a193a

File tree

3 files changed

+108
-10
lines changed

3 files changed

+108
-10
lines changed

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! let pool = BytePool::<Vec<u8>>::new();
99
//!
1010
//! // Allocate a buffer with capacity 1024.
11-
//! let mut buf = pool.alloc(1024);
11+
//! let mut buf = pool.alloc_and_fill(1024);
1212
//!
1313
//! // write some data into it
1414
//! for i in 0..100 {

src/pool.rs

+58-6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ impl<T: Poolable> BytePool<T> {
5656
/// The returned `Block` contains arbitrary data, and must be zeroed or overwritten,
5757
/// in cases this is needed.
5858
pub fn alloc(&self, size: usize) -> Block<'_, T> {
59+
self.alloc_internal(size, false)
60+
}
61+
62+
pub fn alloc_and_fill(&self, size: usize) -> Block<'_, T> {
63+
self.alloc_internal(size, true)
64+
}
65+
66+
pub fn alloc_internal(&self, size: usize, fill: bool) -> Block<'_, T> {
5967
assert!(size > 0, "Can not allocate empty blocks");
6068

6169
// check the last 4 blocks
@@ -64,9 +72,12 @@ impl<T: Poolable> BytePool<T> {
6472
} else {
6573
&self.list_large
6674
};
67-
if let Some(el) = list.pop() {
68-
if el.capacity() == size {
75+
if let Some(mut el) = list.pop() {
76+
if el.capacity() >= size && el.capacity() < size + 1024 {
6977
// found one, reuse it
78+
if fill {
79+
el.resize(size)
80+
}
7081
return Block::new(el, self);
7182
} else {
7283
// put it back
@@ -75,7 +86,11 @@ impl<T: Poolable> BytePool<T> {
7586
}
7687

7788
// allocate a new block
78-
let data = T::alloc(size);
89+
let data = if fill {
90+
T::alloc_and_fill(size)
91+
} else {
92+
T::alloc(size)
93+
};
7994
Block::new(data, self)
8095
}
8196

@@ -90,7 +105,8 @@ impl<T: Poolable> BytePool<T> {
90105

91106
impl<'a, T: Poolable> Drop for Block<'a, T> {
92107
fn drop(&mut self) {
93-
let data = mem::ManuallyDrop::into_inner(unsafe { ptr::read(&self.data) });
108+
let mut data = mem::ManuallyDrop::into_inner(unsafe { ptr::read(&self.data) });
109+
data.reset();
94110
self.pool.push_raw_block(data);
95111
}
96112
}
@@ -138,6 +154,41 @@ unsafe impl<'a, T: StableDeref + Poolable> StableDeref for Block<'a, T> {}
138154
#[cfg(test)]
139155
mod tests {
140156
use super::*;
157+
#[test]
158+
fn append() {
159+
let pool = BytePool::<Vec<u8>>::new();
160+
let mut buf = pool.alloc(4);
161+
assert_eq!(0, buf.len());
162+
assert_eq!(4, buf.capacity());
163+
buf.push(12u8);
164+
assert_eq!(1, buf.len());
165+
buf.extend_from_slice("hello".as_bytes());
166+
assert_eq!(6, buf.len());
167+
buf.clear();
168+
assert_eq!(0, buf.len());
169+
assert!(buf.capacity() > 0);
170+
}
171+
172+
#[test]
173+
fn len_and_capacity() {
174+
let pool = BytePool::<Vec<u8>>::new();
175+
for i in 1..10 {
176+
let buf = pool.alloc_and_fill(i);
177+
assert_eq!(buf.len(), i)
178+
}
179+
for i in 1..10 {
180+
let buf = pool.alloc(i);
181+
assert_eq!(buf.len(), 0)
182+
}
183+
for i in 1..10 {
184+
let buf = pool.alloc_and_fill(i * 10000);
185+
assert_eq!(buf.len(), i * 10000)
186+
}
187+
for i in 1..10 {
188+
let buf = pool.alloc(i * 10000);
189+
assert_eq!(buf.len(), 0)
190+
}
191+
}
141192

142193
#[test]
143194
fn basics_vec_u8() {
@@ -174,6 +225,7 @@ mod tests {
174225
let _slice: &[u8] = &buf;
175226

176227
assert_eq!(buf.capacity(), 10);
228+
buf.resize(10, 0);
177229
for i in 0..10 {
178230
buf[i] = 1;
179231
}
@@ -198,15 +250,15 @@ mod tests {
198250
let pool1 = pool.clone();
199251
let h1 = std::thread::spawn(move || {
200252
for _ in 0..100 {
201-
let mut buf = pool1.alloc(64);
253+
let mut buf = pool1.alloc_and_fill(64);
202254
buf[10] = 10;
203255
}
204256
});
205257

206258
let pool2 = pool.clone();
207259
let h2 = std::thread::spawn(move || {
208260
for _ in 0..100 {
209-
let mut buf = pool2.alloc(64);
261+
let mut buf = pool2.alloc_and_fill(64);
210262
buf[10] = 10;
211263
}
212264
});

src/poolable.rs

+49-3
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,41 @@ use std::hash::{BuildHasher, Hash};
33

44
/// The trait required to be able to use a type in `BytePool`.
55
pub trait Poolable {
6+
fn empty(&self) -> bool;
7+
fn len(&self) -> usize;
68
fn capacity(&self) -> usize;
9+
fn resize(&mut self, count: usize);
10+
fn reset(&mut self);
711
fn alloc(size: usize) -> Self;
12+
fn alloc_and_fill(size: usize) -> Self;
813
}
914

1015
impl<T: Default + Clone> Poolable for Vec<T> {
11-
fn capacity(&self) -> usize {
16+
fn empty(&self) -> bool {
17+
self.len() == 0
18+
}
19+
20+
fn len(&self) -> usize {
1221
self.len()
1322
}
1423

24+
fn capacity(&self) -> usize {
25+
self.capacity()
26+
}
27+
28+
fn resize(&mut self, count: usize) {
29+
self.resize(count, T::default());
30+
}
31+
32+
fn reset(&mut self) {
33+
self.clear();
34+
}
35+
1536
fn alloc(size: usize) -> Self {
37+
Vec::<T>::with_capacity(size)
38+
}
39+
40+
fn alloc_and_fill(size: usize) -> Self {
1641
vec![T::default(); size]
1742
}
1843
}
@@ -22,11 +47,32 @@ where
2247
K: Eq + Hash,
2348
S: BuildHasher + Default,
2449
{
25-
fn capacity(&self) -> usize {
50+
fn empty(&self) -> bool {
51+
self.len() == 0
52+
}
53+
54+
fn len(&self) -> usize {
2655
self.len()
2756
}
2857

58+
fn capacity(&self) -> usize {
59+
self.capacity()
60+
}
61+
62+
fn resize(&mut self, _count: usize) {
63+
// do thing
64+
}
65+
66+
fn reset(&mut self) {
67+
self.clear();
68+
}
69+
2970
fn alloc(size: usize) -> Self {
71+
Self::alloc_and_fill(size)
72+
}
73+
74+
fn alloc_and_fill(size: usize) -> Self {
75+
// not actually filling the HaspMap though
3076
HashMap::with_capacity_and_hasher(size, Default::default())
3177
}
3278
}
@@ -42,7 +88,7 @@ impl<T: Default + Clone> Realloc for Vec<T> {
4288

4389
assert!(new_size > 0);
4490
match new_size.cmp(&self.capacity()) {
45-
Greater => self.resize(new_size, T::default()),
91+
Greater => self.reserve(new_size - self.capacity()),
4692
Less => {
4793
self.truncate(new_size);
4894
self.shrink_to_fit();

0 commit comments

Comments
 (0)