Skip to content

Commit

Permalink
use MaybeInit instead of Option
Browse files Browse the repository at this point in the history
  • Loading branch information
CJP10 committed Aug 22, 2024
1 parent dce27aa commit 09a5da2
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 46 deletions.
27 changes: 0 additions & 27 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,6 @@ use object_pool::{experimental::Pool as ExperimentalPool, Pool};
use std::iter::FromIterator;
use std::sync::Arc;

static KB: usize = 1024;
static MB: usize = 1024 * KB;
static GB: usize = 1024 * MB;
static SIZES: &[usize] = &[
4 * KB,
16 * KB,
64 * KB,
128 * KB,
512 * KB,
1 * MB,
16 * MB,
32 * MB,
64 * MB,
128 * MB,
256 * MB,
512 * MB,
1 * GB,
2 * GB,
3 * GB,
];

fn basics(c: &mut Criterion) {
let mut group = c.benchmark_group("pulling_from_pool");
group.throughput(criterion::Throughput::Elements(1));
Expand Down Expand Up @@ -60,12 +39,6 @@ fn basics(c: &mut Criterion) {
pool.attach(vec);
})
});

// c.bench_function_over_inputs(
// "alloc",
// |b, &&size| b.iter(|| Vec::<u8>::with_capacity(size)),
// SIZES,
// );
}

criterion_group!(benches, basics);
Expand Down
62 changes: 43 additions & 19 deletions src/experimental.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
cell::UnsafeCell,
iter::FromIterator,
mem::ManuallyDrop,
mem::{ManuallyDrop, MaybeUninit},
ops::{Deref, DerefMut},
sync::atomic::Ordering::{Acquire, Relaxed, Release},
};
Expand All @@ -15,15 +15,15 @@ use loom::sync::{atomic::AtomicU64, Arc};
const U64_BITS: usize = u64::BITS as usize;

pub struct Pool<T> {
objects: Box<[UnsafeCell<Option<T>>]>,
objects: Box<[UnsafeCell<MaybeUninit<T>>]>,
bitset: AtomicBitSet,
}

impl<A> FromIterator<A> for Pool<A> {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
let objects = iter
.into_iter()
.map(|o| UnsafeCell::new(Some(o)))
.map(|o| UnsafeCell::new(MaybeUninit::new(o)))
.collect::<Vec<_>>()
.into_boxed_slice();
Self {
Expand All @@ -41,8 +41,8 @@ impl<T> Pool<T> {
value: ManuallyDrop::new(
self.objects[index]
.get()
.replace(None)
.expect("Object should not be null"),
.replace(MaybeUninit::uninit())
.assume_init(),
),
index,
})
Expand All @@ -57,8 +57,8 @@ impl<T> Pool<T> {
value: ManuallyDrop::new(
self.objects[index]
.get()
.replace(None)
.expect("Object should not be null"),
.replace(MaybeUninit::uninit())
.assume_init(),
),
index,
})
Expand All @@ -79,13 +79,30 @@ impl<T> Pool<T> {

fn ret(&self, index: usize, value: T) {
unsafe {
let old = self.objects[index].get().replace(Some(value));
debug_assert!(old.is_none())
self.objects[index].get().write(MaybeUninit::new(value));
}
self.bitset.set(index)
}
}

impl<T> Drop for Pool<T> {
fn drop(&mut self) {
for (i, int) in self.bitset.ints.iter().enumerate() {
let mut bits = int.load(Acquire);
while bits != 0 {
let bit = bits.trailing_zeros() as usize;
bits &= !(1 << bit);
unsafe {
self.objects[i * U64_BITS + bit]
.get()
.read()
.assume_init_drop()
}
}
}
}
}

pub struct Reusable<'a, T> {
pool: &'a Pool<T>,
value: ManuallyDrop<T>,
Expand Down Expand Up @@ -233,8 +250,8 @@ mod tests {
.objects
.iter()
.enumerate()
.map(|(i, x)| (i, (*x.get())))
.all(|(i, x)| x.is_some() && i + 1 == x.unwrap()));
.map(|(i, x)| (i, (*x.get()).assume_init_read()))
.all(|(i, x)| i + 1 == x));
}
}
}
Expand All @@ -245,30 +262,37 @@ mod loom_tests {
use loom::sync::Arc;

#[test]
fn concurrent_pull_sum() {
fn concurrent_pull_mutate() {
loom::model(|| {
let p: Pool<usize> = (0..1).map(|_| 0).collect();
let p: Pool<Vec<_>> = (0..1).map(|_| vec![1, 2, 3]).collect();
let p = Arc::new(p);
let p1 = p.clone();

let h = loom::thread::spawn(move || {
if let Some(mut o) = p1.pull() {
*o += 1
let x = o.remove(0);
assert!(x == 1 || x == 2);
if x == 1 {
assert_eq!(o.as_slice(), &[2, 3]);
}
if x == 2 {
assert_eq!(o.as_slice(), &[3]);
}
}
});

match p.pull() {
Some(mut o) => {
if *o == 0 {
*o += 1;
assert!(o.len() == 2 || o.len() == 3);
if o.len() == 3 {
o.remove(0);
h.join().unwrap();
drop(o);
assert_eq!(*p.pull().unwrap(), 1)
}
assert_eq!(o.as_slice(), &[2, 3]);
}
None => {
h.join().unwrap();
assert_eq!(*p.pull().unwrap(), 1)
assert_eq!(p.pull().unwrap().as_slice(), &[2, 3]);
}
};
});
Expand Down

0 comments on commit 09a5da2

Please sign in to comment.