Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created May 5, 2023 08:58
Show Gist options
  • Save arturaz/3159e791fed31b38730543f3df31100b to your computer and use it in GitHub Desktop.
Save arturaz/3159e791fed31b38730543f3df31100b to your computer and use it in GitHub Desktop.
Rust: async_trait + pin_project
use std::{pin::Pin, future::Future, task::{Context, Poll}};
use async_trait::async_trait;
use pin_project::pin_project;
use std::sync::Arc;
#[async_trait]
pub trait MyAsyncTrait: Send + Sync + Clone {
async fn my_async_fn(&self);
}
#[derive(Clone)]
struct MyAsyncTraitImpl {}
#[async_trait]
impl MyAsyncTrait for MyAsyncTraitImpl {
async fn my_async_fn(&self) {
println!("Hello from my_async_fn");
}
}
#[pin_project]
pub struct MyFuture<'a, T: MyAsyncTrait + 'a> {
async_trait: Arc<T>,
#[pin] future: Option<Pin<Box<dyn Future<Output = ()> + Send + 'a>>>,
}
impl<'a, T: MyAsyncTrait> Future for MyFuture<'a, T> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.as_mut().project();
let maybe_future = this.future.as_mut().as_pin_mut();
match maybe_future {
None => {
println!("Creating future.");
let async_trait = this.async_trait.clone();
let fut = Box::pin(async move {
async_trait.my_async_fn().await;
});
this.future.set(Some(fut));
// After setting the future, call poll again to start polling it.
self.poll(cx)
},
Some(future) => {
println!("Polling future.");
future.poll(cx)
},
}
}
}
#[tokio::main]
async fn main() {
let async_trait = MyAsyncTraitImpl {};
let my_future = MyFuture {
async_trait: Arc::new(async_trait),
future: None,
};
println!("Starting.");
my_future.await;
println!("Done.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment