Closed DelSkayn closed 1 year ago
Note:
The macro async_with
is required because we need a way to create an invariant unique lifetime inside the future.
The following implementation doesn't work because the higher kinded lifetime causes the lifetime to only be valid for the duration of the closure and the future is thus not able to capture it.
async fn async_with<F,Fut,R>(f: F) -> R
where:
F: for<'js> FnOnce(Ctx<'js>) -> Fut,
Fut: Future<Output = R>,
{
...
}
Instead AsyncContex
implements unsafe_async_with
which has the following signiture:
unsafe async fn unsafe_async_with<F,Fut,R>(f: F) -> R
where:
F: FnOnce(NonNull<qjs::JSContext>) -> Fut,
Fut: Future<Output = R>,
{
...
}
The macro makes using this function safe.
Closed in favor of #156
Motivation
Rquickjs support mapping Javascript promises to futures and vice versa via the
Promise
andPromised
types. This allows the rquickjs library to interface with async rust.However the current implementation has a few problems:
First, any access to the Jjavascript runtime in rquickjs has to go through a lock. When the
parallel
feature is enabled this lock is done with a mutex. Blocking locks are a big no-no in async rust. Ideally rquickjs would support asynchronous aware mutexes for locking the runtime.Second, futures in rquickjs currently require that the future is valid for
'static
. This leads to a bit of a problem when trying to use rquickjs functions as basically all functionality has the'js
lifetime attached to it. This prevents functions like the one below from being implemented asCtx
is not valid for 'static' as it has the
'js` lifetime.This severely limits the actual usefulness of the using futures with rquickjs. Ideally futures would only have to be valid for the
'js
lifetime.Implementation
This PR is an attempt to address these problems.
First it introduces
AsyncContext
a version of Context which uses asynchronous locking instead of the blocking lock. This version of context is used together with theasync_with
macro, which allows the with closure to return a future:Second it lifts the
'static
requirement for futures used inPromise
andPromised
. This allows futures to keep Javascript objects, as in the above example, allowing one to implement for example thedelay
function much easier than is currently possible (see #128).Currently futures are send to a separate task where the are polled in depended of whether the runtime is actually locked requiring the futures to be static. This restriction is lifted by keeping any future spawned inside the
async_with
closure inside the runtime lock.