mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2025-01-03 03:05:18 +00:00
qd: replace RefCell with async mutex
Avoid potential run-time borrowing errors across async points. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
ab44cda4b9
commit
8c5fa2a4f9
@ -22,3 +22,4 @@ futures = "0.3.13"
|
||||
usbredirhost = "0.0.1"
|
||||
async-broadcast = "0.3.3"
|
||||
async-trait = "0.1.48"
|
||||
async-lock = "2.3.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
use async_broadcast::{broadcast, Receiver, Sender};
|
||||
use async_lock::RwLock;
|
||||
use futures::Stream;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
default::Default,
|
||||
io::{Read, Write},
|
||||
@ -210,7 +210,7 @@ impl Inner {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UsbRedir {
|
||||
inner: Arc<RefCell<Inner>>,
|
||||
inner: Arc<RwLock<Inner>>,
|
||||
}
|
||||
|
||||
impl UsbRedir {
|
||||
@ -218,7 +218,7 @@ impl UsbRedir {
|
||||
let mut channel = broadcast(1);
|
||||
channel.0.set_overflow(true);
|
||||
Self {
|
||||
inner: Arc::new(RefCell::new(Inner {
|
||||
inner: Arc::new(RwLock::new(Inner {
|
||||
chardevs,
|
||||
channel,
|
||||
handlers: Default::default(),
|
||||
@ -231,7 +231,7 @@ impl UsbRedir {
|
||||
device: &rusb::Device<rusb::Context>,
|
||||
state: bool,
|
||||
) -> Result<bool> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let mut inner = self.inner.write().await;
|
||||
let key = Key::from_device(device);
|
||||
let handled = inner.handlers.contains_key(&key);
|
||||
// We should do better and watch for owner properties changes, but this would require tasks
|
||||
@ -262,19 +262,23 @@ impl UsbRedir {
|
||||
Ok(state)
|
||||
}
|
||||
|
||||
pub fn is_device_connected(&self, device: &rusb::Device<rusb::Context>) -> bool {
|
||||
let inner = self.inner.borrow();
|
||||
pub async fn is_device_connected(&self, device: &rusb::Device<rusb::Context>) -> bool {
|
||||
let inner = self.inner.read().await;
|
||||
|
||||
inner.handlers.contains_key(&Key::from_device(device))
|
||||
}
|
||||
|
||||
pub async fn n_free_channels(&self) -> i32 {
|
||||
self.inner.borrow().n_available_chardev().await as _
|
||||
let inner = self.inner.read().await;
|
||||
|
||||
inner.n_available_chardev().await as _
|
||||
}
|
||||
|
||||
pub fn receive_n_free_channels(&self) -> Pin<Box<dyn Stream<Item = i32>>> {
|
||||
pub async fn receive_n_free_channels(&self) -> Pin<Box<dyn Stream<Item = i32>>> {
|
||||
let inner = self.inner.read().await;
|
||||
|
||||
Box::pin(NFreeChannelsStream {
|
||||
receiver: self.inner.borrow().channel.1.clone(),
|
||||
receiver: inner.channel.1.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,16 @@ impl Handler {
|
||||
widget
|
||||
.model()
|
||||
.connect_items_changed(clone!(@weak widget => move |model, pos, _rm, add| {
|
||||
let usbredir = usbredir.clone();
|
||||
MainContext::default().spawn_local(clone!(@weak model => async move {
|
||||
for pos in pos..pos + add {
|
||||
let item = model.item(pos).unwrap();
|
||||
if let Some(dev) = item.downcast_ref::<rdw::UsbDevice>().unwrap().device() {
|
||||
item.set_property("active", usbredir.is_device_connected(&dev)).unwrap();
|
||||
item.set_property("active", usbredir.is_device_connected(&dev).await).unwrap();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
let usbredir = self.usbredir.clone();
|
||||
widget.connect_device_state_set(move |widget, item, state| {
|
||||
@ -55,7 +58,7 @@ impl Handler {
|
||||
widget
|
||||
.set_property("free-channels", usbredir.n_free_channels().await)
|
||||
.unwrap();
|
||||
let mut n = usbredir.receive_n_free_channels();
|
||||
let mut n = usbredir.receive_n_free_channels().await;
|
||||
while let Some(n) = n.next().await {
|
||||
widget.set_property("free-channels", n).unwrap();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user