scheme-rs 0.2.0

Embedded scheme for the Rust ecosystem
Documentation
//! Threading primitives

use std::{fmt, sync::Arc, thread::{self, sleep}, time::Duration};

use parking_lot::RwLock;
use scheme_rs_macros::bridge;

use crate::{
    exceptions::Exception,
    gc::{Gc, Trace},
    proc::Procedure,
    records::{RecordTypeDescriptor, SchemeCompatible, rtd},
    value::{Cell, Value},
    vectors::Vector,
};

#[derive(Trace)]
pub struct JoinHandle {
    values: Cell,
}

impl fmt::Debug for JoinHandle {
    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
        Ok(())
    }
}

impl SchemeCompatible for JoinHandle {
    fn rtd() -> Arc<RecordTypeDescriptor> {
        rtd!(name: "join-handle", sealed: true, opaque: true)
    }
}

#[bridge(name = "spawn", lib = "(threads (1))")]
pub fn spawn(thunk: Procedure) -> Result<Vec<Value>, Exception> {
    let cell = Gc::new(RwLock::new(Value::undefined()));
    let cell_cloned = cell.clone();
    thread::spawn(move || {
        let mut cell_write = cell_cloned.write();
        // TODO: Handle errors
        *cell_write = Value::from(thunk.call(&[]).unwrap());
    });
    Ok(vec![Value::from_rust_type(JoinHandle {
        values: Cell(cell),
    })])
}

#[bridge(name = "join", lib = "(threads (1))")]
pub fn join(handle: &Value) -> Result<Vec<Value>, Exception> {
    let handle = handle.try_to_rust_type::<JoinHandle>()?;
    let values = handle.values.get().cast_to_scheme_type::<Vector>().unwrap();
    Ok(values.clone_inner_vec())
}

#[bridge(name = "sleep", lib = "(threads (1))")]
pub fn sleep_ms(ms: u64) -> Result<Vec<Value>, Exception> {
    sleep(Duration::from_millis(ms));
    Ok(Vec::new())
}