[go: up one dir, main page]

sdd 4.3.0

Scalable lock-free delayed memory reclaimer
Documentation
use std::sync::atomic::Ordering::Relaxed;
use std::sync::{Arc, Mutex};

use loom::sync::atomic::AtomicUsize;
use loom::thread::{spawn, yield_now};

use crate::{AtomicOwned, AtomicShared, Guard, suspend};

struct A(String, Arc<AtomicUsize>);
impl Drop for A {
    fn drop(&mut self) {
        self.1.fetch_add(1, Relaxed);
    }
}

static SERIALIZER: Mutex<()> = Mutex::new(());

#[test]
fn ebr_owned() {
    let _guard = SERIALIZER.lock().unwrap();
    loom::model(|| {
        let str = "HOW ARE YOU HOW ARE YOU";
        let drop_count = Arc::new(AtomicUsize::new(0));
        let data_owned = AtomicOwned::new(A(str.to_string(), drop_count.clone()));

        let guard = Guard::new();
        let ptr = data_owned.load(Relaxed, &guard);

        let thread = spawn(move || {
            let guard = Guard::new();
            let ptr = data_owned.load(Relaxed, &guard);
            drop(data_owned);

            assert_eq!(ptr.as_ref().unwrap().0, str);
            guard.accelerate();
            drop(guard);

            assert!(suspend());
        });

        assert_eq!(ptr.as_ref().unwrap().0, str);
        guard.accelerate();
        drop(guard);

        while drop_count.load(Relaxed) != 1 {
            Guard::new().accelerate();
            yield_now();
        }

        assert!(thread.join().is_ok());
        assert_eq!(drop_count.load(Relaxed), 1);
    });
}

#[test]
fn ebr_shared() {
    let _guard = SERIALIZER.lock().unwrap();
    loom::model(|| {
        let str = "HOW ARE YOU HOW ARE YOU";
        let drop_count = Arc::new(AtomicUsize::new(0));
        let data_shared = AtomicShared::new(A(str.to_string(), drop_count.clone()));

        let guard = Guard::new();
        let ptr = data_shared.load(Relaxed, &guard);

        let thread = spawn(move || {
            let data_shared_clone = data_shared.get_shared(Relaxed, &Guard::new()).unwrap();
            drop(data_shared);

            assert_eq!(data_shared_clone.0, str);

            let guard = Guard::new();
            let ptr = data_shared_clone.get_guarded_ptr(&guard);
            drop(data_shared_clone);
            guard.accelerate();

            assert_eq!(ptr.as_ref().unwrap().0, str);
            drop(guard);

            assert!(suspend());
        });

        assert_eq!(ptr.as_ref().unwrap().0, str);
        guard.accelerate();
        drop(guard);

        while drop_count.load(Relaxed) != 1 {
            Guard::new().accelerate();
            yield_now();
        }

        assert!(thread.join().is_ok());
        assert_eq!(drop_count.load(Relaxed), 1);
    });
}