Since tokio::sync::RwLockReadGuard<T> implements Deref<T>, you're able to pass it to a function whose signature is like this fn(val: &T). Assuming T is Clone + Send + Sync + 'static is there an elegant way to handle something like this?
For example, if you write something like this, it should compile however it will deadlock.
#[tokio::test]
async fn test() {
let test = std::sync::Arc::new(tokio::sync::RwLock::new(10usize));
async fn announce(val: &usize, test: std::sync::Arc<tokio::sync::RwLock<usize>>) {
println!("{val}");
// This will deadlock
let _ = test.write().await;
}
let read = test.read().await;
announce(&read, test.clone()).await;
}
The way to fix this would've been,
#[tokio::test]
async fn test() {
let test = std::sync::Arc::new(tokio::sync::RwLock::new(10usize));
async fn announce(val: &usize, test: std::sync::Arc<tokio::sync::RwLock<usize>>) {
println!("{val}");
let _ = test.write().await;
}
let read = test.read().await;
let _read = read.to_owned();
drop(read);
announce(&_read, test.clone()).await;
}
I was wondering if there was a clever way to handle this.
I'm not aware of any way to do this. Even if it was possible, what you're asking for looks like at most a partial solution to me, too, anyways: in your own code example, without the drop(read), it would still dead-lock, even though the &_read argument does not borrow from an RwLockReadGuard.
Edit
Oh I think I misunderstood. Yes, I know that the drop is required, and I guess I'm looking for a language semantic that somehow ends up doing a ref-to-ref conversion. If it's impossible that's fine too.