gen_mcf_macro

Crates.iogen_mcf_macro
lib.rsgen_mcf_macro
version0.1.0
created_at2025-06-16 10:18:20.791716+00
updated_at2025-06-16 10:18:20.791716+00
descriptionA 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
repositoryhttps://github.com/ljsnogard/gen_mcf_macro.rs
max_upload_size
id1714113
size17,301
lino (ljsnogard)

documentation

README

gen_mcf_macro

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)]

Usage


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())
    }
}

Commit count: 6

cargo fmt