Skip to content

Instantly share code, notes, and snippets.

@aboglioli
Last active July 29, 2020 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aboglioli/1872b9666c020e15b5aaabc386e5b7ca to your computer and use it in GitHub Desktop.
Save aboglioli/1872b9666c020e15b5aaabc386e5b7ca to your computer and use it in GitHub Desktop.
Trait object with async methods (thanks to async-trait) with Send and Sync markers
use std::sync::Arc;
use async_trait::async_trait; // 0.1.36
#[async_trait]
trait Repo {
async fn find(&self) -> i32;
}
struct RepoImpl;
#[async_trait]
impl Repo for RepoImpl {
async fn find(&self) -> i32 {
23
}
}
struct Serv<R> {
repo: Arc<R>,
dyn_repo: Arc<dyn Repo + Send + Sync>, // it's reponsability of the user to keep it safe for sending (multi-thread)
}
impl<R: Repo> Serv<R> {
async fn exec(&self) -> (i32, i32) {
(2 * self.repo.find().await, self.dyn_repo.find().await / 2)
}
}
struct Context {
repo: Arc<RepoImpl>,
serv: Arc<Serv<RepoImpl>>,
}
#[tokio::main]
async fn main() {
let repo = Arc::new(RepoImpl);
let serv = Arc::new(Serv {
repo: repo.clone(),
dyn_repo: repo.clone(),
});
let g_ctx = Arc::new(Context {
repo: repo.clone(),
serv: serv.clone(),
});
let ctx = Arc::clone(&g_ctx);
let j1 = tokio::spawn(async move {
println!("{}", ctx.serv.exec().await.0);
println!("{}", ctx.repo.find().await);
});
let ctx = Arc::clone(&g_ctx);
let j2 = tokio::spawn(async move {
println!("{}", ctx.serv.exec().await.1);
});
j1.await.unwrap();
j2.await.unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment