I hope this isnt too much of a tangent however I think it is neccesary to understand the problem:
I am currently writing a JIT in rust that traces operations, compiles them to spirv and executes the computations on the GPU (heavily inspired by Dr.Jit from EPFL). I have written a backend for recording the operations (it supports manual reference counting). Every variable is accesed through an index into a vector. I now want to write a frontend for Rust where i have a global instance of the internal representation behind a Mutex. In order to use reference counting I have to decrement the counter for that variable when dropping it. This requires locking the Mutex in the drop function of a Variable.
impl Drop for Var {
fn drop(&mut self) {
IR.lock().unwrap().dec_ref_count(self.0);
}
}
However because recording operations also requires locking the Mutex I reach a deadlock when passing the Variable index to a backend function.
impl<T: Into<Var>> ops::Add<T> for Var {
type Output = Var;
fn add(self, rhs: T) -> Self::Output {
let rhs = rhs.into();
let ret = Self(IR.lock().unwrap().[<$bop:lower>](self.0, rhs.0));
drop(rhs);// This is a workaround and does not seem very idiomatic
ret
}
}
I fixed the problem by manually droping the variable after getting the value. However this does not seem very idiomatic.
Is there a way to structure this in Rust so that I don't get a Deadlock and don't have to repeat the manual drop calls? I would imagine that FFIs would have to deal with somethinge similar relatively often (as C code often uses global states) how do these resolve that issue and what are some resources on Deadlock prevention in Rust?