Function tokenlock::branded::with_branded_token_async
source · [−]pub fn with_branded_token_async<'a, F, R>(f: F) -> impl Future<Output = R> + 'a where
for<'brand> F: IntoBrandedFuture<'brand, Output = R> + 'a,
Available on crate feature
unstable
only.Expand description
Call the provided closure with a brand new BrandedToken
, which can
only be used during the execution of the returned Future
.
This pattern is an asynchronous extension of GhostCell. See
with_branded_token
for the synchronous version.
Example
Passing impl FnOnce(BrandedToken<'_>) -> impl Future
(a free async fn
):
use async_scoped::TokioScope;
use futures::executor::block_on;
use rayon::prelude::*;
use std::pin::Pin;
use tokenlock::{with_branded_token_async, BrandedTokenLock, BrandedToken};
struct Node<'arena, 'brand> {
next: BrandedTokenLock<'brand, Option<&'arena Node<'arena, 'brand>>>,
}
with_branded_token_async(task).await;
async fn task(mut token: BrandedToken<'_>) {
let mut token = token;
let arena = [
Node { next: BrandedTokenLock::wrap(None) },
Node { next: BrandedTokenLock::wrap(None) },
];
// Link the nodes together
arena[0].next.replace(&mut token, Some(&arena[1]));
arena[1].next.replace(&mut token, Some(&arena[0]));
// Unlike `Cell`, this doesn't prevent shared read-only access
TokioScope::scope_and_block(|s| {
for node in arena.iter() {
let token = token.borrow();
s.spawn(async move {
println!("{:p} is linked to {:p}", node, node.next.get(&*token).unwrap());
});
}
});
}
Passing (T, impl FnOnce(T, BrandedToken<'_>) -> impl Future)
:
let mut value = 0;
with_branded_token_async((&mut value, task)).await;
assert_eq!(value, 42);
async fn task(borrowed_value: &mut i32, _token: BrandedToken<'_>) {
*borrowed_value = 42;
}
Closures don’t work currently:
ⓘ
with_branded_token_async(|token: BrandedToken<'_>| async move {
let _ = token;
}).await;