[go: up one dir, main page]

state 0.5.3

A library for safe and effortless global and thread-local state management.
Documentation
#![cfg(loom)]

use loom::sync::Arc;
use loom::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use loom::thread;

#[test]
fn init_exclusive() {
    use state::private::init::Init;

    const THREADS: usize = 2;

    loom::model(|| {
        let init = Arc::new(Init::new());
        let value = Arc::new(AtomicUsize::new(0));

        let mut threads = vec![];
        for _ in 1..(THREADS + 1) {
            let init = init.clone();
            let value = value.clone();
            let thread = thread::spawn(move || {
                if init.needed() {
                    value.fetch_add(1, Relaxed);
                    init.mark_complete();
                }
            });

            threads.push(thread);
        }

        for thread in threads {
            thread.join().unwrap();
        }

        assert_eq!(value.load(Relaxed), 1);
    });
}

#[test]
fn init_completed() {
    use state::private::init::Init;

    const THREADS: usize = 2;

    loom::model(|| {
        let init = Arc::new(Init::new());
        let value = Arc::new(AtomicUsize::new(0));

        let mut threads = vec![];
        for _ in 1..(THREADS + 1) {
            let init = init.clone();
            let value = value.clone();
            let thread = thread::spawn(move || {
                if init.has_completed() {
                    assert_eq!(value.load(Relaxed), 1);
                }

                if init.needed() {
                    value.fetch_add(1, Relaxed);
                    init.mark_complete();
                }
            });

            threads.push(thread);
        }

        for thread in threads {
            thread.join().unwrap();
        }

        assert_eq!(value.load(Relaxed), 1);
    });
}

#[test]
fn storage() {
    use state::Storage;

    const THREADS: usize = 2;

    loom::model(|| {
        let storage = Arc::new(Storage::<u8>::new());

        let mut threads = vec![];
        for _ in 1..(THREADS + 1) {
            let storage = storage.clone();
            let thread = thread::spawn(move || {
                storage.set(10);
                assert_eq!(storage.try_get(), Some(&10));
                assert!(!storage.set(20));
                assert_eq!(storage.try_get(), Some(&10));
            });

            threads.push(thread);
        }

        for thread in threads {
            thread.join().unwrap();
        }
    });
}

#[test]
fn container1() {
    use state::Container;

    const THREADS: usize = 2;

    loom::model(|| {
        let container = Arc::new(<Container![Send + Sync]>::new());

        let mut threads = vec![];
        for _ in 1..(THREADS + 1) {
            let container = container.clone();
            let thread = thread::spawn(move || {
                assert_eq!(container.try_get::<isize>(), None);
                container.set::<usize>(10);
                assert_eq!(container.try_get::<usize>(), Some(&10));
                assert!(!container.set::<usize>(11));
                assert_eq!(container.try_get::<usize>(), Some(&10));
            });

            threads.push(thread);
        }

        for thread in threads {
            thread.join().unwrap();
        }

        assert_eq!(container.len(), 1);
    });
}

#[test]
fn container2() {
    use state::Container;

    const THREADS: usize = 2;

    loom::model(|| {
        let container = Arc::new(<Container![Send + Sync]>::new());

        let mut threads = vec![];
        for _ in 1..(THREADS + 1) {
            let container = container.clone();
            let thread = thread::spawn(move || {
                if container.try_get::<Box<usize>>().is_some() {
                    assert!(!container.set::<Box<usize>>(Box::new(10)));
                }

                container.set::<Box<usize>>(Box::new(10));
                assert_eq!(**container.try_get::<Box<usize>>().unwrap(), 10);
            });

            threads.push(thread);
        }

        for thread in threads {
            thread.join().unwrap();
        }

        assert_eq!(container.len(), 1);
    });
}