parsec 0.3.1

Parallel Systems for Entity Components
Documentation
extern crate parsec;

use parsec::Storage;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};

#[derive(Clone, Debug)]
struct CompInt(i8);
impl parsec::Component for CompInt {
    type Storage = parsec::VecStorage<CompInt>;
}
#[derive(Clone, Debug)]
struct CompBool(bool);
impl parsec::Component for CompBool {
    type Storage = parsec::HashMapStorage<CompBool>;
}

fn create_world() -> parsec::Scheduler {
    let mut w = parsec::World::new();
    w.register::<CompInt>();
    w.register::<CompBool>();
    parsec::Scheduler::new(w, 4)
}

#[test]
fn wait() {
    let mut scheduler = create_world();

    for _ in 0..100 {
        let found_ent_0 = Arc::new(AtomicBool::new(false));
        let found_ent_1 = Arc::new(AtomicBool::new(false));

        scheduler.world.create_now()
            .with(CompInt(7))
            .with(CompBool(false))
            .build();

        let marker = found_ent_0.clone();
        scheduler.run1w1r(move |b: &mut CompBool, r: &CompInt| {
            b.0 = r.0 == 7;
            marker.store(true, Ordering::SeqCst);
        });
        let marker = found_ent_1.clone();
        scheduler.run0w2r(move |r: &CompInt, b: &CompBool| {
            assert_eq!(r.0, 7);
            assert_eq!(b.0, true);
            marker.store(true, Ordering::SeqCst);
        });
        scheduler.wait();

        assert_eq!(found_ent_0.load(Ordering::SeqCst), true);
        assert_eq!(found_ent_1.load(Ordering::SeqCst), true);
    }
}

#[should_panic]
#[test]
fn task_panics() {
    let mut scheduler = create_world();
    scheduler.world.create_now()
        .with(CompInt(7))
        .with(CompBool(false))
        .build();

    scheduler.run(|args| {
        args.fetch(|_| ());
        panic!();
    });
    scheduler.wait();
}


#[should_panic]
#[test]
fn task_panics_args_captured() {
    let mut scheduler = create_world();
    scheduler.world.create_now()
        .with(CompInt(7))
        .with(CompBool(false))
        .build();

    scheduler.run(|_| {
        panic!();
    });
    scheduler.wait();
}

#[test]
fn dynamic_create() {
    let mut scheduler = create_world();

    for _ in 0..1_000 {
        scheduler.run(|arg| {
            arg.fetch(|_| ());
            arg.create();
        });
        scheduler.wait();
    }
}

#[test]
fn dynamic_deletion() {
    let mut scheduler = create_world();

    for _ in 0..1_000 {
        scheduler.run(|arg| {
            arg.fetch(|_| ());
            let e = arg.create();
            arg.delete(e);
        });
        scheduler.wait();
    }
}

#[test]
fn dynamic_create_and_delete() {
    use std::mem::swap;
    let mut scheduler = create_world();

    let (mut ent0, mut ent1) = (
        Arc::new(Mutex::new(None)),
        Arc::new(Mutex::new(None))
    );

    for i in 0..1_000 {
        let e = ent0.clone();
        scheduler.run(move |arg| {
            arg.fetch(|_| ());
            let mut e = e.lock().unwrap();
            *e = Some(arg.create());
        });
        if i >= 1 {
            let e = ent1.clone();
            scheduler.run(move |arg| {
                arg.fetch(|_| ());
                let mut e = e.lock().unwrap();
                arg.delete(e.take().unwrap());
            })
        }
        scheduler.wait();
        swap(&mut ent1, &mut ent0)
    }
}