bombs 0.2.1

Efficient single-producer multi-consumer channel types.
Documentation
// todo: test `Flame` as well.

#[test]
fn threaded_unchecked_u32() {
    use bombs::Bomb;
    use loom::{ thread, hint };

    loom::model(|| {
        let (fuse, bomb) = Bomb::new();

        let handle = {
            let bomb_clone = bomb.clone();

            let h = thread::spawn(move || {
                let bomb = bomb_clone;

                thread::yield_now();

                // Do nothing, but drop in here.
                // Loom is exhaustive so this is to test
                // what happens when an unsynchronised bomb
                // is the final to drop.
                drop(bomb);
            });

            // Idk why but this casues issues otherwise.
            drop(bomb);

            h
        };

        let flame = fuse.light(5_u32);

        thread::yield_now();
        // while !flame.extinguished() { hint::spin_loop() }

        handle.join().unwrap();
    });
}

#[test]
fn threaded_multi_u32() {
    use bombs::MultiBomb;
    use loom::{ thread, hint };

    loom::model(|| {
        let (mut fuse, bomb) = MultiBomb::new();

        let handle = {
            let mut bomb_clone = bomb.clone();

            let h = thread::spawn(move || {
                let value = loop {
                    match bomb_clone.exploded() {
                        Some(v) => break v,
                        None => hint::spin_loop(),
                    }
                };
                assert_eq!(value, 5);

                let value = loop {
                    match bomb_clone.exploded() {
                        Some(v) => break v,
                        None => hint::spin_loop(),
                    }
                };
                assert_eq!(value, 24);
            });

            // Idk why but this casues issues otherwise.
            drop(bomb);

            h
        };

        let flame = fuse.light(5_u32);

        thread::yield_now();
        // while !flame.extinguished() { hint::spin_loop(); }

        let flame = fuse.light(24);

        thread::yield_now();
        // while !flame.extinguished() { hint::spin_loop(); }

        handle.join().unwrap();
    });
}

#[test]
fn threaded_u32() {
    use bombs::Bomb;
    use loom::{ thread, hint };

    loom::model(|| {
        let (fuse, bomb) = Bomb::new();

        let handle = {
            let bomb_clone = bomb.clone();

            let h = thread::spawn(move || {
                while let None = bomb_clone.exploded() { hint::spin_loop(); }

                assert_eq!(bomb_clone.exploded(), Some(&5));
            });

            // Idk why but this casues issues otherwise.
            drop(bomb);

            h
        };

        let flame = fuse.light(5_u32);

        thread::yield_now();
        // while !flame.extinguished() { hint::spin_loop() }

        handle.join().unwrap();
    });
}

#[test]
fn simple_u32() {
    use bombs::Bomb;

    loom::model(|| {
        let (fuse, bomb) = Bomb::new();

        let bomb_clone = bomb.clone();

        assert_eq!(bomb.exploded(), None);
        assert_eq!(bomb_clone.exploded(), None);

        let flame = fuse.light(7_u32);

        assert_eq!(bomb.exploded(), Some(&7));
        assert_eq!(bomb_clone.exploded(), Some(&7));

        // assert!(!flame.extinguished());

        drop(bomb_clone);
        drop(bomb);

        // assert!(flame.extinguished());
    });
}

#[test]
fn empty_u32() {
    use bombs::Bomb;

    loom::model(|| {
        let (fuse, bomb) = Bomb::<u32>::new();
        let bomb_clone = bomb.clone();

        assert_eq!(bomb.exploded(), None);
        assert_eq!(bomb_clone.exploded(), None);

        let _fuse = std::hint::black_box(fuse);
    });
}

#[test]
fn box_dropped_correctly() {
    use bombs::*;

    loom::model(|| {
        let (fuse, bomb) = Bomb::new();

        let bomb_clone = bomb.clone();

        fuse.light(Box::new("Hello world".to_owned()));

        // No double-drop
        assert_eq!(&**bomb.exploded().unwrap(), "Hello world");
        assert_eq!(&**bomb_clone.exploded().unwrap(), "Hello world");
        assert_eq!(&**bomb.exploded().unwrap(), "Hello world");
    });
}

#[test]
fn multi_box_dropped_correctly() {
    use bombs::*;

    loom::model(|| {
        let (mut fuse, mut bomb) = MultiBomb::new();

        let mut bomb_clone = bomb.clone();

        fuse.light(Box::new("Hello".to_owned()));
        fuse.light(Box::new(" world".to_owned()));

        // No double-drop
        assert_eq!(&*bomb.exploded().unwrap(), "Hello");
        assert_eq!(&*bomb_clone.exploded().unwrap(), "Hello");
        assert_eq!(&*bomb.exploded().unwrap(), " world");
        assert_eq!(&*bomb_clone.exploded().unwrap(), " world");

        assert_eq!(bomb.exploded(), None);
        assert_eq!(bomb_clone.exploded(), None);
    });
}