waitcell 0.4.1

A cell type containing a value which may not yet be available.
Documentation
//
// Copyright (C) 2020 Nathan Sharp.
//
// This file is available under either the terms of the Apache License, Version
// 2.0 or the MIT License, at your discretion.
//

use std::sync::Arc;
use std::thread::{sleep, spawn, JoinHandle};
use std::time::Duration;

use super::WaitCell;

#[test]
fn uninit_try_get() {
    assert!(WaitCell::<()>::new().try_get().is_none())
}

#[test]
fn init_try_get() {
    assert!(WaitCell::<()>::with_default().try_get().is_some())
}

#[test]
fn uninit_init() {
    let later = WaitCell::<()>::new();
    assert!(later.try_get().is_none());

    later.init(());
    assert!(later.try_get().is_some());
}

#[test]
fn init_twice() {
    let later = WaitCell::<usize>::new();
    assert!(later.try_get().is_none());

    later.init(42);
    assert_eq!(later.try_get(), Some(&42));

    assert!(!later.try_init(|| 24));
    assert_eq!(later.try_get(), Some(&42));
}

#[test]
fn stress() {
    let later = Arc::new(WaitCell::<usize>::new());

    let mut threads = Vec::<JoinHandle<()>>::with_capacity(10);

    {
        let later = later.clone();
        threads.push(spawn(move || {
            sleep(Duration::from_secs(3));
            later.init(42);
            sleep(Duration::from_secs(3));
            assert!(!later.try_init(|| 24));
        }));
    }

    for _ in 0..2 {
        let later = later.clone();
        threads.push(spawn(move || {
            sleep(Duration::from_secs(5));

            for _ in 0..100000 {
                assert!(!later.try_init(|| 24));
            }
        }));
    }

    for _ in 0..2 {
        let later = later.clone();
        threads.push(spawn(move || {
            for _ in 0..100000 {
                assert!(later.try_get().is_none());
            }

            sleep(Duration::from_secs(5));

            for _ in 0..100000 {
                assert_eq!(later.try_get(), Some(&42usize));
            }
        }));
    }

    for _ in 0..2 {
        let later = later.clone();
        threads.push(spawn(move || {
            assert_eq!(later.get(), &42usize);
        }));
    }

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