use crate::internals::lincowcell_async::{LinCowCell, LinCowCellReadTxn, LinCowCellWriteTxn};
include!("impl.rs");
impl<K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
BptreeMap<K, V>
{
pub async fn read<'x>(&'x self) -> BptreeMapReadTxn<'x, K, V> {
let inner = self.inner.read().await;
BptreeMapReadTxn { inner }
}
pub async fn write<'x>(&'x self) -> BptreeMapWriteTxn<'x, K, V> {
let inner = self.inner.write().await;
BptreeMapWriteTxn { inner }
}
}
impl<'a, K: Clone + Ord + Debug + Sync + Send + 'static, V: Clone + Sync + Send + 'static>
BptreeMapWriteTxn<'a, K, V>
{
pub async fn commit(self) {
self.inner.commit().await;
}
}
#[cfg(test)]
mod tests {
use super::BptreeMap;
use crate::internals::bptree::node::{assert_released, L_CAPACITY};
use rand::seq::SliceRandom;
use std::iter::FromIterator;
#[tokio::test]
async fn test_bptree2_map_basic_write() {
let bptree: BptreeMap<usize, usize> = BptreeMap::new();
{
let mut bpwrite = bptree.write().await;
bpwrite.insert(0, 0);
bpwrite.insert(1, 1);
assert!(bpwrite.get(&0) == Some(&0));
assert!(bpwrite.get(&1) == Some(&1));
bpwrite.insert(2, 2);
bpwrite.commit().await;
}
{
let mut bpwrite = bptree.write().await;
bpwrite.clear();
}
{
let bpwrite = bptree.write().await;
assert!(bpwrite.get(&0) == Some(&0));
assert!(bpwrite.get(&1) == Some(&1));
}
std::mem::drop(bptree);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_cursed_get_mut() {
let bptree: BptreeMap<usize, usize> = BptreeMap::new();
{
let mut w = bptree.write().await;
w.insert(0, 0);
w.commit().await;
}
let r1 = bptree.read().await;
{
let mut w = bptree.write().await;
let cursed_zone = w.get_mut(&0).unwrap();
*cursed_zone = 1;
w.commit().await;
}
let r2 = bptree.read().await;
assert!(r1.get(&0) == Some(&0));
assert!(r2.get(&0) == Some(&1));
std::mem::drop(r1);
std::mem::drop(r2);
std::mem::drop(bptree);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_from_iter_1() {
let ins: Vec<usize> = (0..(L_CAPACITY << 4)).collect();
let map = BptreeMap::from_iter(ins.into_iter().map(|v| (v, v)));
{
let w = map.write().await;
assert!(w.verify());
println!("{:?}", w.tree_density());
}
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_from_iter_2() {
let mut rng = rand::thread_rng();
let mut ins: Vec<usize> = (0..(L_CAPACITY << 4)).collect();
ins.shuffle(&mut rng);
let map = BptreeMap::from_iter(ins.into_iter().map(|v| (v, v)));
{
let w = map.write().await;
assert!(w.verify());
assert!(w.verify());
}
std::mem::drop(map);
assert_released();
}
async fn bptree_map_basic_concurrency(lower: usize, upper: usize) {
let map = BptreeMap::new();
{
let mut w = map.write().await;
w.extend((0..lower).map(|v| (v, v)));
w.commit().await;
}
let r = map.read().await;
assert!(r.len() == lower);
for i in 0..lower {
assert!(r.contains_key(&i))
}
{
let mut w = map.write().await;
w.extend((lower..upper).map(|v| (v, v)));
w.commit().await;
}
assert!(r.len() == lower);
let r2 = map.read().await;
assert!(r2.len() == upper);
for i in 0..upper {
assert!(r2.contains_key(&i))
}
{
let mut w = map.write().await;
for i in 0..upper {
assert!(w.remove(&i).is_some())
}
w.commit().await;
}
assert!(r.len() == lower);
assert!(r2.len() == upper);
for i in 0..upper {
assert!(r2.contains_key(&i))
}
let r3 = map.read().await;
assert!(r3.len() == 0);
std::mem::drop(r);
std::mem::drop(r2);
std::mem::drop(r3);
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_acb_order() {
let map = BptreeMap::new();
{
let mut w = map.write().await;
w.extend((0..(L_CAPACITY * 2)).map(|v| (v * 2, v * 2)));
w.commit().await;
}
let ro_txn_a = map.read().await;
{
let mut w = map.write().await;
w.insert(1, 1);
w.commit().await;
}
let ro_txn_b = map.read().await;
{
let mut w = map.write().await;
w.insert(1, 10001);
w.commit().await;
}
let ro_txn_c = map.read().await;
assert!(ro_txn_b.verify());
std::mem::drop(ro_txn_b);
assert!(ro_txn_a.verify());
assert!(ro_txn_c.verify());
std::mem::drop(ro_txn_a);
std::mem::drop(ro_txn_c);
std::mem::drop(map);
assert_released();
}
#[tokio::test]
async fn test_bptree2_map_weird_txn_behaviour() {
let map: BptreeMap<usize, usize> = BptreeMap::new();
let mut wr = map.write().await;
let rd = map.read().await;
wr.insert(1, 1);
assert!(rd.get(&1) == None);
wr.commit().await;
assert!(rd.get(&1) == None);
}
#[tokio::test]
#[cfg_attr(miri, ignore)]
async fn test_bptree2_map_basic_concurrency_small() {
bptree_map_basic_concurrency(100, 200).await
}
#[tokio::test]
#[cfg_attr(miri, ignore)]
async fn test_bptree2_map_basic_concurrency_large() {
bptree_map_basic_concurrency(10_000, 20_000).await
}
}