| Crates.io | gen_mcf_macro |
| lib.rs | gen_mcf_macro |
| version | 0.1.0 |
| created_at | 2025-06-16 10:18:20.791716+00 |
| updated_at | 2025-06-16 10:18:20.791716+00 |
| description | A macro working with crate `abs_sync` v0.2 to generate codes and types needed to implement `Future` and `TrMayCancel` for a pattern that supports graceful cancellation in async programming. |
| homepage | |
| repository | https://github.com/ljsnogard/gen_mcf_macro.rs |
| max_upload_size | |
| id | 1714113 |
| size | 17,301 |
Assumed to work with following unstable features:
// Allow for implementation of the AsyncFn*
#![feature(async_fn_traits)]
// To enable `extern "rust-call" fn` which is used in `impl AsyncFnOnce`
#![feature(unboxed_closures)]
// To enable `type CallOnceFuture = impl ::core::future::Future<Output = Self::Output>;`
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]
use abs_sync::cancellation::{NonCancellableToken, TrMayCancel, TrCancellationToken};
/// # Usage Rules:
/// 0. Must be an `async fn`;
/// 1. Use one and only one lifetime and DO NOT name a lifetime with a underscore suffix;
/// 2. The last param must be the cancellation token type and constrained with: `TrCancellationToken`;
/// 3. Use a where clause to constrain the cancel token type;
/// 4. If an argument is not `Copy` then it should be borrowed;
#[gen_may_cancel_future(DoThing)]
async fn do_thing_async<'f, A, B, C>(
a: &'f mut A,
b: &'f mut B,
l: usize, // copy, ok
x: &'f Result<A, B>, // see rule 4
cancel: Pin<&'f mut C>, // see rule 2
) -> R
where
A: Send,
B: Sync,
C: TrCancellationToken,
{
// ...
}
Which expands to codes:
async fn do_thing_async<'f, A, B, C>(
a: &'f mut A,
b: &'f mut B,
l: usize,
x: &'f Result<A, B>,
cancel: Pin<&'f mut C>,
) -> usize
where
A: Send,
B: Sync,
C: TrCancellationToken,
{
42
}
pub struct DoThingAsync<'f, A, B>(
&'f mut A,
&'f mut B,
usize,
&'f Result<A, B>,
)
where
A: Send,
B: Sync;
pub struct DoThingFuture<'f, A, B, C>
where
A: Send,
B: Sync,
C: TrCancellationToken,
{
params_: DoThingAsync<'f, A, B>,
cancel_: Pin<&'f mut C>,
future_: Option<
<DoThingFutureState<
'f,
A,
B,
C,
> as ::core::ops::AsyncFnOnce<()>>::CallOnceFuture,
>,
}
struct DoThingFutureState<'f, A, B, C>(
::core::pin::Pin<&'f mut DoThingFuture<'f, A, B, C>>,
)
where
A: Send,
B: Sync,
C: TrCancellationToken;
impl<'f, A, B> ::core::future::IntoFuture for DoThingAsync<'f, A, B>
where
A: Send,
B: Sync,
{
type IntoFuture = DoThingFuture<
'f,
A,
B,
::abs_sync::cancellation::NonCancellableToken,
>;
type Output = usize;
fn into_future(self) -> Self::IntoFuture {
DoThingFuture {
params_: self,
cancel_: ::abs_sync::cancellation::NonCancellableToken::pinned(),
future_: Option::None,
}
}
}
impl<'f, A, B> ::abs_sync::cancellation::TrMayCancel<'f>
for DoThingAsync<'f, A, B>
where
A: Send,
B: Sync,
{
type MayCancelOutput = usize;
fn may_cancel_with<
'cancel_,
C: ::abs_sync::cancellation::TrCancellationToken,
>(
self,
cancel: ::core::pin::Pin<&'cancel_ mut C>,
) -> impl ::core::future::Future<Output = Self::MayCancelOutput>
where
Self: 'cancel_,
{
DoThingFuture {
params_: self,
cancel_: cancel,
future_: Option::None,
}
}
}
impl<'f, A, B, C> ::core::future::Future for DoThingFuture<'f, A, B, C>
where
A: Send,
B: Sync,
C: TrCancellationToken,
{
type Output = usize;
fn poll(
self: ::core::pin::Pin<&mut Self>,
cx: &mut ::core::task::Context<'_>,
) -> ::core::task::Poll<Self::Output> {
let mut this = unsafe {
let p = self.get_unchecked_mut();
::core::ptr::NonNull::new_unchecked(p)
};
loop {
let mut fut_field_ptr = unsafe {
let ptr = &mut this.as_mut().future_;
::core::ptr::NonNull::new_unchecked(ptr)
};
let opt_fut = unsafe { fut_field_ptr.as_mut() };
if let Option::Some(fut) = opt_fut {
let fut_pin = unsafe { ::core::pin::Pin::new_unchecked(fut) };
break fut_pin.poll(cx);
} else {
let state = DoThingFutureState(unsafe {
::core::pin::Pin::new_unchecked(this.as_mut())
});
let fut = AsyncFnOnce::async_call_once(state, ());
let fut_field_mut = unsafe { fut_field_ptr.as_mut() };
*fut_field_mut = Option::Some(fut);
}
}
}
}
impl<A, B, C> ::core::ops::AsyncFnOnce<()> for DoThingFutureState<'_, A, B, C>
where
A: Send,
B: Sync,
C: TrCancellationToken,
{
type Output = usize;
type CallOnceFuture = impl ::core::future::Future<Output = Self::Output>;
extern "rust-call" fn async_call_once(self, _: ()) -> Self::CallOnceFuture {
let f = unsafe { self.0.get_unchecked_mut() };
let p = &mut f.params_;
self::do_thing_async(p.0, p.1, p.2, p.3, f.cancel_.as_mut())
}
}