So I have a resource that I can get that needs to be locked to one user at a time. It is accessed by an HTTP call. The library we are using for making the HTTP call makes use of asynchronous calls.
I would like to free up the resource on destruction of the class, if it hasn't been freed up already in the positive test case flow.
The problem is, you can't call asynchronous functions from the drop() function.
I found this:
https://docs.rs/async-drop/0.0.0/async_drop/
and this article:
So the answer basically appears to be "no."
But that doesn't solve the problem of what is the correct/idiomatic way to solve the problem?
Is there a known common solution to this? All I could find was people asking questions.
Here's my Cargo.toml
[package]
name = "asyncdrop"
version = "0.1.0"
authors = ["rustuser <pirera3226@mailetk.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "0.2", features = ["full"] }
anyhow = "1.0"
and the source file example of the problem.
use std::sync::Arc;
use tokio::sync::RwLock;
struct Operation {
handle: Arc<RwLock<Option<u32>>>,
}
impl Operation {
fn new() -> Operation {
Operation {
handle: Arc::new(RwLock::new(Some(1))),
}
}
async fn lock_resource(&self) -> Result<(), anyhow::Error> {
// pretend we're making an http call here
let mut locked = self.handle.write().await; // I use tokio here to force the issue that I need to call await.
*locked = Some(1);
return Ok(());
}
async fn unlock_resource(&self) -> Result<(), anyhow::Error> {
// pretend we're making another http call here
let mut locked = self.handle.write().await;
if *locked == None {
return Ok(());
}
*locked = None;
return Ok(());
}
async fn go(&self) -> Result<(), anyhow::Error> {
self.lock_resource().await?;
println!("Uh oh, I exhibit an error and return early.");
if true {
return Err(anyhow::anyhow!("failure"));
}
self.unlock_resource().await?;
return Ok(());
}
}
impl Drop for Operation {
fn drop(&mut self) {
println!("Operation going out of scope, about to free_data()");
self.unlock_resource().await;
}
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
println!("Hello, world!");
let example = Operation::new();
example.go().await?;
return Ok(()); // Drop should free the resource here.
}