1

I have been scouring the docs to find a way to call an asynchronous function synchronously. Specifically, I am trying to call tokio::sync::mutex::lock from a Display implementation to provide useful information.

This is an example of what I want to be able to do:

struct MyStruct(Mutex<u64>);

impl fmt::Display for MyStruct {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Current Value: {}", self.0.lock().await)
    }
}

fn main() {
    let s = MyStruct(Mutex::new(8));
    println!("{}", s)
}

playground

I could get over it in this case and just avoid it all together, but this seems like a serious limitation which I am running into.

My first thought was to use tokio::task::spawn and then use the join handle, however, that does not seem to be possible as the join function is itself a future. I would just call poll on the future returned from the mutex, but I cannot find anywhere how to provide the Context parameter, which leads me to believe it is an internal executor thing.

When I was digging around I discovered async_std::task::block_on which seems to do exactly what I need but I would like to stick to Tokio. Am I missing something or is this actually a limitation with the Tokio framework?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Eadword
  • 160
  • 1
  • 11
  • The duplicate [applied to your case](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f0aca387a99d4b732d62311abddbde06). – Shepmaster Jan 01 '20 at 18:45
  • @Shepmaster does it really require creating a new runtime just to lock a single mutex? Is there much overhead if you create a same-thread executor? – Eadword Jan 01 '20 at 19:09
  • I don't really know if there is much overhead to creating an executor, but that's basically your only option. You want to resolve a future before continuing on, so you need something to drive the future to completion. Without an executor, *none* of the code in the future would ever be executed. – Shepmaster Jan 02 '20 at 00:00

0 Answers0