-
I'm wondering if I'm thinking of a code like below. The struct ControllerState {
is_connected: bool,
callback: PyObject,
// other fields ...
}
impl ControllerState {
fn do_something(&mut self) {
todo!()
}
}
#[pyclass]
struct Controller {
state: std::sync::Mutex<ControllerState>
}
#[pymethods]
impl Controller {
// set a callback function called when detatched from the device
fn set_on_disconnected(&mut self, callback: PyObject) {
self.state.lock().unwrap().callback = callback;
}
// do something with the device using internal data
fn do_something(&self) {
self.state.lock().unwrap().do_something()
}
// when detatched from the device,
// the following function will be called from
// poling thread that watches the communication status
// between PC and device
fn fire_disconnected(&mut self) {
let mut state = self.state.lock().unwrap();
state.is_connected = false;
Python::with_gil(|py| {
state.callback.call0(py).unwrap();
})
}
} The documentation says that instance methods marked with
If the code above is problematic, can the following code be a workaround? #[pymethods]
impl Controller {
fn do_something(&self) {
// using Python::with_gil because I can not get py token from &self of pyclass
Python::with_gil(|py| {
py.allow_threads(|| {
// This does not touch Python object,
// only accesses to Rust data.
self.state.lock().unwrap().do_something()
})
})
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This sounds like a variant of https://pyo3.rs/v0.22.2/faq#im-experiencing-deadlocks-using-pyo3-with-lazy_static-or-once_cell But yes, the GIL is just another Mutex. You should always release one before locking the other. |
Beta Was this translation helpful? Give feedback.
This sounds like a variant of https://pyo3.rs/v0.22.2/faq#im-experiencing-deadlocks-using-pyo3-with-lazy_static-or-once_cell
But yes, the GIL is just another Mutex. You should always release one before locking the other.