use std::sync::{Mutex, MutexGuard}; struct Wallet { lock: Mutex<()>, client: Client, } struct Client { // ... } impl Wallet { fn new(client: Client) -> Self { Self { lock: Mutex::new(()), client } } async fn async_with_lock(&self, f: F) -> R where F: FnOnce(&mut Client) -> R + Send, R: Send, { let mut lock: MutexGuard<()> = self.lock.lock().await; f(&mut self.client) } async fn my_locked_method(&self) { my_macro!(client, my_client_method); } fn my_regular_method(&self) { client.my_other_client_method(); } } impl Client { fn my_client_method(&mut self) { // ... } } macro_rules! my_macro { ($wallet:expr, $method:ident) => { { $wallet.async_with_lock(|client| async move { client.$method().await; }).await; } } } async fn main() { let client = Client { /* ... */ }; let wallet = Wallet::new(client); wallet.my_locked_method().await; wallet.my_regular_method(); }