process-sync 0.2.2

Synchronization primitives for multiprocess environments
Documentation
mod common;

use libc::fork;
pub use process_sync::private::SharedMemoryObject;
use process_sync::{private::check_libc_err, SharedCondvar, SharedMutex};

use common::{sleep, TestOutput};

fn child0(test_output: &mut TestOutput, mutex: &mut SharedMutex, condvar: &mut SharedCondvar) -> ! {
    test_output.write_line("child0 lock()");
    mutex.lock().expect("lock() failed");
    test_output.write_line("child0 wait()");
    condvar.wait(mutex).expect("wait() failed");
    mutex.unlock().expect("unlock() failed");
    test_output.write_line("child0 unlocked");
    sleep(5);

    test_output.write_line("child0 FIRST_TEST_END");
    sleep(100);

    test_output.write_line("child0 lock()");
    mutex.lock().expect("lock() failed");
    test_output.write_line("child0 wait()");
    condvar.wait(mutex).expect("wait() failed");
    test_output.write_line("child0 unlock()");
    mutex.unlock().expect("unlock() failed");
    test_output.write_line("child0 unlocked");

    std::process::exit(0);
}

fn child1(test_output: &mut TestOutput, mutex: &mut SharedMutex, condvar: &mut SharedCondvar) {
    sleep(10);
    test_output.write_line("child1 lock()");
    mutex.lock().expect("lock() failed");
    test_output.write_line("child1 wait()");
    condvar.wait(mutex).expect("wait() failed");
    mutex.unlock().expect("unlock() failed");
    sleep(10);
    test_output.write_line("child1 unlocked");

    test_output.write_line("child1 FIRST_TEST_END");
    sleep(50);

    test_output.write_line("child1 lock()");
    mutex.lock().expect("lock() failed");
    test_output.write_line("child1 wait()");
    condvar.wait(mutex).expect("wait() failed");
    test_output.write_line("child1 unlock()");
    mutex.unlock().expect("unlock() failed");
    test_output.write_line("child1 unlocked");

    std::process::exit(0);
}

fn parent(test_output: &mut TestOutput, _mutex: &mut SharedMutex, condvar: &mut SharedCondvar) {
    sleep(40);
    test_output.write_line("parent notify_all()");
    condvar.notify_all().expect("notify_all() failed");

    test_output.write_line("parent FIRST_TEST_END");
    sleep(300);

    test_output.write_line("parent notify_one()");
    condvar.notify_one().expect("notify_one() failed");
    sleep(10);
    test_output.write_line("parent notify_one()");
    condvar.notify_one().expect("notify_one() failed");

    sleep(40);
}

fn main() {
    let mut test_output = TestOutput::new(&[
        "child0 lock()",
        "child0 wait()",
        "child1 lock()",
        "child1 wait()",
        "parent notify_all()",
        "parent FIRST_TEST_END",
        "child0 unlocked",
        "child0 FIRST_TEST_END",
        "child1 unlocked",
        "child1 FIRST_TEST_END",
        "child1 lock()",
        "child1 wait()",
        "child0 lock()",
        "child0 wait()",
        "parent notify_one()",
        "child1 unlock()",
        "child1 unlocked",
        "parent notify_one()",
        "child0 unlock()",
        "child0 unlocked",
    ]);

    let mut mutex = SharedMutex::new().expect("cannot create SharedMutex");
    let mut condvar = SharedCondvar::new().expect("cannot create SharedCondvar");

    let pid = check_libc_err(unsafe { fork() }).expect("fork failed");
    if pid == 0 {
        child0(&mut test_output, &mut mutex, &mut condvar);
    } else {
        let pid = check_libc_err(unsafe { fork() }).expect("fork failed");
        if pid == 0 {
            child1(&mut test_output, &mut mutex, &mut condvar);
        } else {
            parent(&mut test_output, &mut mutex, &mut condvar);
        }
    }
}