Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/sharded-slab/src/tests/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 17 kB image not shown  

Quelle  loom_pool.rs

  Sprache: Rust
 

use super::util::*;
use crate::{clear::Clear, sync::alloc, Pack, Pool};
use loom::{
    sync::{
        atomic::{AtomicBool, Ordering},
        Condvar, Mutex,
    },
    thread,
};
use std::sync::Arc;

#[derive(Default, Debug)]
struct State {
    is_dropped: AtomicBool,
    is_cleared: AtomicBool,
    id: usize,
}

impl State {
    fn assert_clear(&self) {
        assert!(!self.is_dropped.load(Ordering::SeqCst));
        assert!(self.is_cleared.load(Ordering::SeqCst));
    }

    fn assert_not_clear(&self) {
        assert!(!self.is_dropped.load(Ordering::SeqCst));
        assert!(!self.is_cleared.load(Ordering::SeqCst));
    }
}

impl PartialEq for State {
    fn eq(&self, other: &State) -> bool {
        self.id.eq(&other.id)
    }
}

#[derive(Default, Debug)]
struct DontDropMe(Arc<State>);

impl PartialEq for DontDropMe {
    fn eq(&self, other: &DontDropMe) -> bool {
        self.0.eq(&other.0)
    }
}

impl DontDropMe {
    fn new(id: usize) -> (Arc<State>, Self) {
        let state = Arc::new(State {
            is_dropped: AtomicBool::new(false),
            is_cleared: AtomicBool::new(false),
            id,
        });
        (state.clone(), Self(state))
    }
}

impl Drop for DontDropMe {
    fn drop(&mut self) {
        test_println!("-> DontDropMe drop: dropping data {:?}"self.0.id);
        self.0.is_dropped.store(true, Ordering::SeqCst)
    }
}

impl Clear for DontDropMe {
    fn clear(&mut self) {
        test_println!("-> DontDropMe clear: clearing data {:?}"self.0.id);
        self.0.is_cleared.store(true, Ordering::SeqCst);
    }
}

#[test]
fn dont_drop() {
    run_model("dont_drop", || {
        let pool: Pool<DontDropMe> = Pool::new();
        let (item1, value) = DontDropMe::new(1);
        test_println!("-> dont_drop: Inserting into pool {}", item1.id);
        let idx = pool
            .create_with(move |item| *item = value)
            .expect("create_with");

        item1.assert_not_clear();

        test_println!("-> dont_drop: clearing idx: {}", idx);
        pool.clear(idx);

        item1.assert_clear();
    });
}

#[test]
fn concurrent_create_with_clear() {
    run_model("concurrent_create_with_clear", || {
        let pool: Arc<Pool<DontDropMe>> = Arc::new(Pool::new());
        let pair = Arc::new((Mutex::new(None), Condvar::new()));

        let (item1, value) = DontDropMe::new(1);
        let idx1 = pool
            .create_with(move |item| *item = value)
            .expect("create_with");
        let p = pool.clone();
        let pair2 = pair.clone();
        let test_value = item1.clone();
        let t1 = thread::spawn(move || {
            let (lock, cvar) = &*pair2;
            test_println!("-> making get request");
            assert_eq!(p.get(idx1).unwrap().0.id, test_value.id);
            let mut next = lock.lock().unwrap();
            *next = Some(());
            cvar.notify_one();
        });

        test_println!("-> making get request");
        let guard = pool.get(idx1);

        let (lock, cvar) = &*pair;
        let mut next = lock.lock().unwrap();
        // wait until we have a guard on the other thread.
        while next.is_none() {
            next = cvar.wait(next).unwrap();
        }
        // the item should be marked (clear returns true)...
        assert!(pool.clear(idx1));
        // ...but the value shouldn't be removed yet.
        item1.assert_not_clear();

        t1.join().expect("thread 1 unable to join");

        drop(guard);
        item1.assert_clear();
    })
}

#[test]
fn racy_clear() {
    run_model("racy_clear", || {
        let pool = Arc::new(Pool::new());
        let (item, value) = DontDropMe::new(1);

        let idx = pool
            .create_with(move |item| *item = value)
            .expect("create_with");
        assert_eq!(pool.get(idx).unwrap().0.id, item.id);

        let p = pool.clone();
        let t2 = thread::spawn(move || p.clear(idx));
        let r1 = pool.clear(idx);
        let r2 = t2.join().expect("thread 2 should not panic");

        test_println!("r1: {}, r2: {}", r1, r2);

        assert!(
            !(r1 && r2),
            "Both threads should not have cleared the value"
        );
        assert!(r1 || r2, "One thread should have removed the value");
        assert!(pool.get(idx).is_none());
        item.assert_clear();
    })
}

#[test]
fn clear_local_and_reuse() {
    run_model("take_remote_and_reuse", || {
        let pool = Arc::new(Pool::new_with_config::<TinyConfig>());

        let idx1 = pool
            .create_with(|item: &mut String| {
                item.push_str("hello world");
            })
            .expect("create_with");
        let idx2 = pool
            .create_with(|item| item.push_str("foo"))
            .expect("create_with");
        let idx3 = pool
            .create_with(|item| item.push_str("bar"))
            .expect("create_with");

        assert_eq!(pool.get(idx1).unwrap(), String::from("hello world"));
        assert_eq!(pool.get(idx2).unwrap(), String::from("foo"));
        assert_eq!(pool.get(idx3).unwrap(), String::from("bar"));

        let first = idx1 & (!crate::page::slot::Generation::<TinyConfig>::MASK);
        assert!(pool.clear(idx1));

        let idx1 = pool
            .create_with(move |item| item.push_str("h"))
            .expect("create_with");

        let second = idx1 & (!crate::page::slot::Generation::<TinyConfig>::MASK);
        assert_eq!(first, second);
        assert!(pool.get(idx1).unwrap().capacity() >= 11);
    })
}

#[test]
fn create_mut_guard_prevents_access() {
    run_model("create_mut_guard_prevents_access", || {
        let pool = Arc::new(Pool::<String>::new());
        let guard = pool.create().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        thread::spawn(move || {
            assert!(pool2.get(key).is_none());
        })
        .join()
        .unwrap();
    });
}

#[test]
fn create_mut_guard() {
    run_model("create_mut_guard", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.create().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        guard.push_str("Hello world");
        drop(guard);

        t1.join().unwrap();
    });
}

#[test]
fn create_mut_guard_2() {
    run_model("create_mut_guard_2", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.create().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        guard.push_str("Hello world");
        let t2 = thread::spawn(move || {
            test_dbg!(pool3.get(key));
        });
        drop(guard);

        t1.join().unwrap();
        t2.join().unwrap();
    });
}

#[test]
fn create_mut_guard_downgrade() {
    run_model("create_mut_guard_downgrade", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.create().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        guard.push_str("Hello world");
        let guard = guard.downgrade();
        let t2 = thread::spawn(move || {
            test_dbg!(pool3.get(key));
        });

        t1.join().unwrap();
        t2.join().unwrap();
        assert_eq!(guard, "Hello world".to_owned());
    });
}

#[test]
fn create_mut_guard_downgrade_clear() {
    run_model("create_mut_guard_downgrade_clear", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.create().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();

        guard.push_str("Hello world");
        let guard = guard.downgrade();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });
        let t2 = thread::spawn(move || {
            test_dbg!(pool3.clear(key));
        });

        assert_eq!(guard, "Hello world".to_owned());
        drop(guard);

        t1.join().unwrap();
        t2.join().unwrap();

        assert!(pool.get(key).is_none());
    });
}

#[test]
fn create_mut_downgrade_during_clear() {
    run_model("create_mut_downgrade_during_clear", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.create().unwrap();
        let key: usize = guard.key();
        guard.push_str("Hello world");

        let pool2 = pool.clone();
        let guard = guard.downgrade();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.clear(key));
        });

        t1.join().unwrap();

        assert_eq!(guard, "Hello world".to_owned());
        drop(guard);

        assert!(pool.get(key).is_none());
    });
}

#[test]
fn ownedref_send_out_of_local() {
    run_model("ownedref_send_out_of_local", || {
        let pool = Arc::new(Pool::<alloc::Track<String>>::new());
        let key1 = pool
            .create_with(|item| item.get_mut().push_str("hello"))
            .expect("create item 1");
        let key2 = pool
            .create_with(|item| item.get_mut().push_str("goodbye"))
            .expect("create item 2");

        let item1 = pool.clone().get_owned(key1).expect("get key1");
        let item2 = pool.clone().get_owned(key2).expect("get key2");
        let pool2 = pool.clone();

        test_dbg!(pool.clear(key1));

        let t1 = thread::spawn(move || {
            assert_eq!(item1.get_ref(), &String::from("hello"));
            drop(item1);
        });
        let t2 = thread::spawn(move || {
            assert_eq!(item2.get_ref(), &String::from("goodbye"));
            test_dbg!(pool2.clear(key2));
            drop(item2);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        assert!(pool.get(key1).is_none());
        assert!(pool.get(key2).is_none());
    });
}

#[test]
fn ownedrefs_outlive_pool() {
    run_model("ownedrefs_outlive_pool", || {
        let pool = Arc::new(Pool::<alloc::Track<String>>::new());
        let key1 = pool
            .create_with(|item| item.get_mut().push_str("hello"))
            .expect("create item 1");
        let key2 = pool
            .create_with(|item| item.get_mut().push_str("goodbye"))
            .expect("create item 2");

        let item1_1 = pool.clone().get_owned(key1).expect("get key1");
        let item1_2 = pool.clone().get_owned(key1).expect("get key1 again");
        let item2 = pool.clone().get_owned(key2).expect("get key2");
        drop(pool);

        let t1 = thread::spawn(move || {
            assert_eq!(item1_1.get_ref(), &String::from("hello"));
            drop(item1_1);
        });

        let t2 = thread::spawn(move || {
            assert_eq!(item2.get_ref(), &String::from("goodbye"));
            drop(item2);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        assert_eq!(item1_2.get_ref(), &String::from("hello"));
    });
}

#[test]
fn ownedref_ping_pong() {
    run_model("ownedref_ping_pong", || {
        let pool = Arc::new(Pool::<alloc::Track<String>>::new());
        let key1 = pool
            .create_with(|item| item.get_mut().push_str("hello"))
            .expect("create item 1");
        let key2 = pool
            .create_with(|item| item.get_mut().push_str("world"))
            .expect("create item 2");

        let item1 = pool.clone().get_owned(key1).expect("get key1");
        let pool2 = pool.clone();
        let pool3 = pool.clone();

        let t1 = thread::spawn(move || {
            assert_eq!(item1.get_ref(), &String::from("hello"));
            pool2.clear(key1);
            item1
        });

        let t2 = thread::spawn(move || {
            let item2 = pool3.clone().get_owned(key2).unwrap();
            assert_eq!(item2.get_ref(), &String::from("world"));
            pool3.clear(key1);
            item2
        });

        let item1 = t1.join().unwrap();
        let item2 = t2.join().unwrap();

        assert_eq!(item1.get_ref(), &String::from("hello"));
        assert_eq!(item2.get_ref(), &String::from("world"));
    });
}

#[test]
fn ownedref_drop_from_other_threads() {
    run_model("ownedref_drop_from_other_threads", || {
        let pool = Arc::new(Pool::<alloc::Track<String>>::new());
        let key1 = pool
            .create_with(|item| item.get_mut().push_str("hello"))
            .expect("create item 1");
        let item1 = pool.clone().get_owned(key1).expect("get key1");

        let pool2 = pool.clone();

        let t1 = thread::spawn(move || {
            let pool = pool2.clone();
            let key2 = pool
                .create_with(|item| item.get_mut().push_str("goodbye"))
                .expect("create item 1");
            let item2 = pool.clone().get_owned(key2).expect("get key1");
            let t2 = thread::spawn(move || {
                assert_eq!(item2.get_ref(), &String::from("goodbye"));
                test_dbg!(pool2.clear(key1));
                drop(item2)
            });
            assert_eq!(item1.get_ref(), &String::from("hello"));
            test_dbg!(pool.clear(key2));
            drop(item1);
            (t2, key2)
        });

        let (t2, key2) = t1.join().unwrap();
        test_dbg!(pool.get(key1));
        test_dbg!(pool.get(key2));

        t2.join().unwrap();

        assert!(pool.get(key1).is_none());
        assert!(pool.get(key2).is_none());
    });
}

#[test]
fn create_owned_mut_guard() {
    run_model("create_owned_mut_guard", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        guard.push_str("Hello world");
        drop(guard);

        t1.join().unwrap();
    });
}

#[test]
fn create_owned_mut_guard_send() {
    run_model("create_owned_mut_guard", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        let t2 = thread::spawn(move || {
            guard.push_str("Hello world");
            drop(guard);
        });

        t1.join().unwrap();
        t2.join().unwrap();
    });
}

#[test]
fn create_owned_mut_guard_2() {
    run_model("create_owned_mut_guard_2", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        guard.push_str("Hello world");
        let t2 = thread::spawn(move || {
            test_dbg!(pool3.get(key));
        });
        drop(guard);

        t1.join().unwrap();
        t2.join().unwrap();
    });
}

#[test]
fn create_owned_mut_guard_downgrade() {
    run_model("create_owned_mut_guard_downgrade", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        guard.push_str("Hello world");

        let key: usize = guard.key();

        let pool2 = pool.clone();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });

        let guard = guard.downgrade();
        let t2 = thread::spawn(move || {
            assert_eq!(pool3.get(key).unwrap(), "Hello world".to_owned());
        });

        t1.join().unwrap();
        t2.join().unwrap();
        assert_eq!(guard, "Hello world".to_owned());
    });
}

#[test]
fn create_owned_mut_guard_downgrade_then_clear() {
    run_model("create_owned_mut_guard_downgrade_then_clear", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();

        let pool2 = pool.clone();

        guard.push_str("Hello world");
        let guard = guard.downgrade();
        let pool3 = pool.clone();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.get(key));
        });
        let t2 = thread::spawn(move || {
            test_dbg!(pool3.clear(key));
        });

        assert_eq!(guard, "Hello world".to_owned());
        drop(guard);

        t1.join().unwrap();
        t2.join().unwrap();

        assert!(pool.get(key).is_none());
    });
}

#[test]
fn create_owned_mut_downgrade_during_clear() {
    run_model("create_owned_mut_downgrade_during_clear", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();
        guard.push_str("Hello world");

        let pool2 = pool.clone();
        let guard = guard.downgrade();
        let t1 = thread::spawn(move || {
            test_dbg!(pool2.clear(key));
        });

        t1.join().unwrap();

        assert_eq!(guard, "Hello world".to_owned());
        drop(guard);

        assert!(pool.get(key).is_none());
    });
}

#[test]
fn create_mut_downgrade_during_clear_by_other_thead() {
    run_model("create_mut_downgrade_during_clear_by_other_thread", || {
        let pool = Arc::new(Pool::<String>::new());
        let mut guard = pool.clone().create_owned().unwrap();
        let key: usize = guard.key();
        guard.push_str("Hello world");

        let pool2 = pool.clone();
        let t1 = thread::spawn(move || {
            let guard = guard.downgrade();
            assert_eq!(guard, "Hello world".to_owned());
            drop(guard);
        });

        let t2 = thread::spawn(move || {
            test_dbg!(pool2.clear(key));
        });

        test_dbg!(pool.get(key));

        t1.join().unwrap();
        t2.join().unwrap();
    });
}

Messung V0.5 in Prozent
C=87 H=91 G=88

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.