ā All posts
Deno / Non-blocking FFI Calls
Posted On 01.31.2022
Sometimes, we want to call an FFI function that is CPU-bound. This would block the main thread. For example, in this sleep_and_scream
method from Rust, we use std::thread::sleep
to hang the function for a while, then print out some text:
use std::{thread, time::Duration};
#[no_mangle]
pub fn sleep_and_scream(millis: u64) {
thread::sleep(Duration::from_millis(millis));
println!("WAAAAAAAAAAAA!!!!!!!!!!!");
}
Import and call this function in Deno would cause the program to hang for a few seconds before everything can be printed out:
const libName = './target/debug/libdeno_blocking_demo.dylib';
const lib = Deno.dlopen(libName, {
sleep_and_scream: {
parameters: ["u64"],
result: "void",
}
});
lib.symbols.sleep_and_scream(2000);
console.log("It's Deno!!!!");
The output:
<hang for 2 seconds>
WAAAAAAAAAAAA!!!!!!!!!!!
It's Deno!!!!
From version 1.15, Deno supports marking an FFI function as nonblocking
, which will make the function run on a dedicated blocking thread and return a Promise
.
const libName = './target/debug/libdeno_blocking_demo.dylib';
const lib = Deno.dlopen(libName, {
sleep_and_scream: {
parameters: ["u64"],
result: "void",
nonblocking: true // <-- add this
}
});
lib.symbols.sleep_and_scream(2000)
.then(() => console.log("Finished!")); // <-- It's a promise now
console.log("It's Deno!!!!");
With this updated program, the output would be:
It's Deno!!!!
<hang for 2 seconds>
WAAAAAAAAAAAA!!!!!!!!!!!
Finished!