use loom::sync::Arc;
use super::{explore, memtable, memtable_with_budget, probe};
const SMALL_BUDGET: usize = 256;
pub fn a_slice_outlives_every_memtable_handle() {
explore(
"a_slice_outlives_every_memtable_handle",
256,
8,
|witness| {
let mt = Arc::new(memtable());
mt.put(probe(b"k").prefixed_user_key(), b"pinned", 1);
let reader = {
let mt = Arc::clone(&mt);
let witness = witness.clone();
loom::thread::spawn(move || {
let (_, value) = mt.get(&probe(b"k")).expect("`k` was seeded");
let value = value.expect("`k` is a live value");
let last = Arc::strong_count(&mt) == 1;
drop(mt);
assert_eq!(value.as_slice(), b"pinned");
if last {
witness.record();
}
})
};
let writer = {
let mt = Arc::clone(&mt);
loom::thread::spawn(move || {
mt.put(probe(b"z").prefixed_user_key(), b"later", 2);
drop(mt);
})
};
drop(mt);
reader.join().expect("reader");
writer.join().expect("writer");
},
);
}
pub fn a_slice_survives_the_arena_growing_a_new_chunk() {
explore(
"a_slice_survives_the_arena_growing_a_new_chunk",
64,
8,
|witness| {
let mt = Arc::new(memtable_with_budget(SMALL_BUDGET));
mt.put(probe(b"k").prefixed_user_key(), b"pinned", 1);
let reserved_before = mt.reserved_size();
assert!(reserved_before > 0, "the seed took the arena's first chunk");
let reader = {
let mt = Arc::clone(&mt);
let witness = witness.clone();
loom::thread::spawn(move || {
let (_, value) = mt.get(&probe(b"k")).expect("`k` was seeded");
let value = value.expect("`k` is a live value");
let grew = mt.reserved_size() > reserved_before;
drop(mt);
assert_eq!(
value.as_slice(),
b"pinned",
"A2, A3, A5: a pinned slice reads its own chunk's bytes"
);
if grew {
witness.record();
}
})
};
let writer = {
let mt = Arc::clone(&mt);
loom::thread::spawn(move || {
mt.put(probe(b"big").prefixed_user_key(), &[0xab; SMALL_BUDGET], 2);
drop(mt);
})
};
drop(mt);
reader.join().expect("reader");
writer.join().expect("writer");
},
);
}