Skip to content

Commit 8a9422e

Browse files
remove mutex in favor of SegQueue
1 parent 5724886 commit 8a9422e

File tree

2 files changed

+21
-19
lines changed

2 files changed

+21
-19
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ is-it-maintained-open-issues = { repository = "dignifiedquire/byte-pool" }
1515

1616
[features]
1717
default = []
18+
19+
[dependencies]
20+
crossbeam-queue = "0.2.0"

src/lib.rs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ use std::fmt;
2929
use std::mem;
3030
use std::ops::{Deref, DerefMut};
3131
use std::ptr;
32-
use std::sync::Mutex;
32+
33+
use crossbeam_queue::SegQueue;
3334

3435
/// A pool of byte slices, that reuses memory.
3536
#[derive(Debug)]
3637
pub struct BytePool {
37-
list_large: Mutex<Vec<Vec<u8>>>,
38-
list_small: Mutex<Vec<Vec<u8>>>,
38+
list_large: SegQueue<Vec<u8>>,
39+
list_small: SegQueue<Vec<u8>>,
3940
}
4041

4142
/// The size at which point values are allocated in the small list, rather than the big.
@@ -58,8 +59,8 @@ impl fmt::Debug for Block<'_> {
5859
impl Default for BytePool {
5960
fn default() -> Self {
6061
BytePool {
61-
list_large: Mutex::new(Vec::new()),
62-
list_small: Mutex::new(Vec::new()),
62+
list_large: SegQueue::new(),
63+
list_small: SegQueue::new(),
6364
}
6465
}
6566
}
@@ -78,22 +79,20 @@ impl BytePool {
7879
assert!(size > 0, "Can not allocate empty blocks");
7980

8081
// check the last 4 blocks
81-
let mut lock = if size < SPLIT_SIZE {
82-
self.list_small.lock().unwrap()
82+
let list = if size < SPLIT_SIZE {
83+
&self.list_small
8384
} else {
84-
self.list_large.lock().unwrap()
85+
&self.list_large
8586
};
86-
let end = lock.len();
87-
let start = if end > 4 { end - 4 } else { 0 };
88-
89-
for i in start..end {
90-
if lock[i].capacity() == size {
87+
if let Ok(el) = list.pop() {
88+
if el.capacity() == size {
9189
// found one, reuse it
92-
let data = lock.remove(i);
93-
return Block::new(data, self);
90+
return Block::new(el, self);
91+
} else {
92+
// put it back
93+
list.push(el);
9494
}
9595
}
96-
drop(lock);
9796

9897
// allocate a new block
9998
let data = vec![0u8; size];
@@ -102,9 +101,9 @@ impl BytePool {
102101

103102
fn push_raw_block(&self, block: Vec<u8>) {
104103
if block.capacity() < SPLIT_SIZE {
105-
self.list_small.lock().unwrap().push(block);
104+
self.list_small.push(block);
106105
} else {
107-
self.list_large.lock().unwrap().push(block);
106+
self.list_large.push(block);
108107
}
109108
}
110109
}
@@ -241,6 +240,6 @@ mod tests {
241240
h2.join().unwrap();
242241

243242
// two threads allocating in parallel will need 2 buffers
244-
assert_eq!(pool.list_small.lock().unwrap().len(), 2);
243+
assert!(pool.list_small.len() <= 2);
245244
}
246245
}

0 commit comments

Comments
 (0)