Blocking tasks
Blocking tasks are the simplest kind of task, they're closures that take a GcFrame
which are sent to the runtime thread and executed in a dynamic scope. As their name implies, when a blocking task is executed the runtime thread is blocked until the task has completed.
use jlrs::prelude::*;
fn main() {
let (async_handle, thread_handle) = Builder::new()
.n_threads(4)
.async_runtime(Tokio::<3>::new(false))
.spawn()
.expect("cannot init Julia");
let dispatch = async_handle
.blocking_task(|mut frame| {
// Safety: we're just printing a string
unsafe { Value::eval_string(&mut frame, "println(\"Hello from the async runtime\")") }
.expect("caught an exception");
});
let recv = dispatch
.try_dispatch()
.expect("cannot dispatch task");
recv.blocking_recv()
.expect("cannot receive result");
std::mem::drop(async_handle);
thread_handle.join().expect("runtime thread panicked")
}
Sending a task is a two-step process. The AsyncHandle::blocking_task
method returns an instance of Dispatch
, which provides sync and async methods to dispatch the task. If the backing channel is full, Dispatch::try_dispatch
fails but returns itself as an Err
to allow retrying later.
If the task has been dispatched successfully, the receiving half of tokio's oneshot-channel is returned which will eventually receive the result of that task.