From d752e88abf3e338fdfefbfd9ca2d9b0f7e54c0ce Mon Sep 17 00:00:00 2001 From: Reinout Meliesie Date: Thu, 4 Sep 2025 13:25:48 +0200 Subject: [PATCH] refactor(networkmanager): make dbus connection a ClientInner field Should be more efficient as the connection will now only be created once. --- src/clients/networkmanager/mod.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/clients/networkmanager/mod.rs b/src/clients/networkmanager/mod.rs index da7e5bf..4ee6a6f 100644 --- a/src/clients/networkmanager/mod.rs +++ b/src/clients/networkmanager/mod.rs @@ -46,8 +46,7 @@ struct ClientInner { controller_sender: broadcast::Sender, sender: broadcast::Sender, device_watchers: RwLock, DeviceWatcher>>, - // TODO: Maybe find some way to late-init a dbus connection here - // so we can just clone it when we need it instead of awaiting it every time + dbus_connection: RwLock>, } #[derive(Clone, Debug)] @@ -60,10 +59,12 @@ impl ClientInner { let (controller_sender, _) = broadcast::channel(64); let (sender, _) = broadcast::channel(8); let device_watchers = RwLock::new(HashMap::new()); + let dbus_connection = RwLock::new(None); ClientInner { controller_sender, sender, device_watchers, + dbus_connection, } } @@ -89,8 +90,7 @@ impl ClientInner { async fn watch_devices_list(&'static self) -> Result<()> { debug!("D-Bus devices list watcher starting"); - let dbus_connection = Connection::system().await?; - let root = DbusProxy::new(&dbus_connection).await?; + let root = DbusProxy::new(&self.dbus_connection().await?).await?; let mut devices_changes = root.receive_all_devices_changed().await; while let Some(devices_change) = devices_changes.next().await { @@ -133,15 +133,14 @@ impl ClientInner { &'static self, mut receiver: broadcast::Receiver, ) -> Result<()> { - let dbus_connection = Connection::system().await?; - while let Result::Ok(event) = receiver.recv().await { match event { ModuleToClientEvent::NewController => { debug!("Client received NewController event"); for device_path in self.device_watchers.read().await.keys() { - let device = DeviceDbusProxy::new(&dbus_connection, device_path).await?; + let dbus_connection = &self.dbus_connection().await?; + let device = DeviceDbusProxy::new(dbus_connection, device_path).await?; let interface = device.interface().await?.to_string(); let r#type = device.device_type().await?; @@ -197,6 +196,21 @@ impl ClientInner { Ok(()) } + + async fn dbus_connection(&self) -> Result { + let dbus_connection_guard = self.dbus_connection.read().await; + if let Some(dbus_connection) = &*dbus_connection_guard { + Ok(dbus_connection.clone()) + } else { + // Yes it's a bit awkward to first obtain a read lock and then a write lock but it + // needs to happen only once, and after that all read lock acquisitions will be + // instant + drop(dbus_connection_guard); + let dbus_connection = Connection::system().await?; + *self.dbus_connection.write().await = Some(dbus_connection.clone()); + Ok(dbus_connection) + } + } } pub fn create_client() -> ClientResult {