From af216ee08cafd6bd444691b767a3b47f765d57d0 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Tue, 7 Jun 2022 00:54:33 +1200 Subject: [PATCH] Async tasks --- daemon/src/ctrl_anime/mod.rs | 75 ++++++++++++++++------- daemon/src/ctrl_aura/controller.rs | 85 +++++++++++--------------- daemon/src/ctrl_profiles/controller.rs | 21 ++++--- daemon/src/ctrl_profiles/zbus.rs | 21 ++++--- daemon/src/daemon.rs | 32 ++++------ daemon/src/lib.rs | 21 ++++++- design-patterns.md | 2 +- 7 files changed, 150 insertions(+), 107 deletions(-) diff --git a/daemon/src/ctrl_anime/mod.rs b/daemon/src/ctrl_anime/mod.rs index 41916b8b..d9da60d8 100644 --- a/daemon/src/ctrl_anime/mod.rs +++ b/daemon/src/ctrl_anime/mod.rs @@ -1,10 +1,10 @@ pub mod config; pub mod zbus; -use ::zbus::blocking::Connection; +use ::zbus::Connection; use async_trait::async_trait; use log::{error, info, warn}; -use logind_zbus::manager::ManagerProxyBlocking; +use logind_zbus::manager::ManagerProxy; use rog_anime::{ error::AnimeError, usb::{ @@ -15,6 +15,7 @@ use rog_anime::{ }; use rog_supported::AnimeSupportedFunctions; use rusb::{Device, DeviceHandle}; +use smol::{stream::StreamExt, Executor}; use std::{ cell::RefCell, error::Error, @@ -298,33 +299,63 @@ impl CtrlAnime { } } -pub struct CtrlAnimeTask<'a> { +pub struct CtrlAnimeTask { _inner: Arc>, - _c: Connection, - manager: ManagerProxyBlocking<'a>, } -impl<'a> CtrlAnimeTask<'a> { - pub fn new(inner: Arc>) -> Self { - let connection = - Connection::system().expect("CtrlAnimeTask could not create dbus connection"); - - let manager = ManagerProxyBlocking::new(&connection) - .expect("CtrlAnimeTask could not create ManagerProxy"); - - Self { - _inner: inner, - _c: connection, - manager, - } +impl CtrlAnimeTask { + pub async fn new(inner: Arc>) -> CtrlAnimeTask { + Self { _inner: inner } } } #[async_trait] -impl<'a> crate::CtrlTask for CtrlAnimeTask<'a> { - async fn do_task(&self) -> Result<(), RogError> { - self.manager.receive_prepare_for_shutdown()?.next(); - self.manager.receive_prepare_for_sleep()?.next(); +impl crate::CtrlTask for CtrlAnimeTask { + async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + let connection = Connection::system() + .await + .expect("CtrlAnimeTask could not create dbus connection"); + + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlAnimeTask could not create ManagerProxy"); + + let x = self._inner.clone(); + executor + .spawn(async move { + if let Ok(p) = manager.receive_prepare_for_sleep().await { + p.for_each(|_| { + if let Ok(_lock) = x.clone().try_lock() { + info!("AniMe received sleep event (this feature is not yet complete)"); + // lock.config.system + } + }) + .await; + } + }) + .detach(); + + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlAnimeTask could not create ManagerProxy"); + + let x = self._inner.clone(); + executor + .spawn(async move { + if let Ok(p) = manager.receive_prepare_for_shutdown().await { + p.for_each(|_| { + if let Ok(_lock) = x.clone().try_lock() { + info!( + "AniMe received shutdown event (this feature is not yet complete)" + ); + // lock.config.system + } + }) + .await; + } + }) + .detach(); + Ok(()) } } diff --git a/daemon/src/ctrl_aura/controller.rs b/daemon/src/ctrl_aura/controller.rs index ce35a725..07ed81c0 100644 --- a/daemon/src/ctrl_aura/controller.rs +++ b/daemon/src/ctrl_aura/controller.rs @@ -8,7 +8,7 @@ use crate::{ }; use async_trait::async_trait; use log::{info, warn}; -use logind_zbus::manager::ManagerProxyBlocking; +use logind_zbus::manager::ManagerProxy; use rog_aura::{ usb::{ LED_APPLY, LED_AWAKE_OFF_SLEEP_OFF, LED_AWAKE_OFF_SLEEP_ON, LED_AWAKE_ON_SLEEP_OFF, @@ -17,12 +17,13 @@ use rog_aura::{ AuraEffect, LedBrightness, LED_MSG_LEN, }; use rog_supported::LedSupportedFunctions; +use smol::{stream::StreamExt, Executor}; use std::fs::OpenOptions; use std::io::{Read, Write}; use std::path::Path; use std::sync::Arc; use std::sync::Mutex; -use zbus::blocking::Connection; +use zbus::Connection; use crate::GetSupported; @@ -55,50 +56,13 @@ pub struct CtrlKbdLed { pub config: AuraConfig, } -pub struct CtrlKbdLedTask<'a> { +pub struct CtrlKbdLedTask { inner: Arc>, - _c: Connection, - _manager: ManagerProxyBlocking<'a>, } -impl<'a> CtrlKbdLedTask<'a> { +impl CtrlKbdLedTask { pub fn new(inner: Arc>) -> Self { - let connection = - Connection::system().expect("CtrlKbdLedTask could not create dbus connection"); - - let manager = ManagerProxyBlocking::new(&connection) - .expect("CtrlKbdLedTask could not create ManagerProxy"); - - // let c1 = inner.clone(); - // // Run this action when the system wakes up from sleep - // manager - // .connect_prepare_for_sleep(move |sleep| { - // if !sleep { - // let c1 = c1.clone(); - // spawn(move || { - // // wait a fraction for things to wake up properly - // //std::thread::sleep(Duration::from_millis(100)); - // loop { - // if let Ok(ref mut lock) = c1.try_lock() { - // lock.set_brightness(lock.config.brightness).ok(); - // break; - // } - // } - // }); - // } - // Ok(()) - // }) - // .map_err(|err| { - // warn!("CtrlAnimeTask: new() {}", err); - // err - // }) - // .ok(); - - Self { - inner, - _c: connection, - _manager: manager, - } + Self { inner } } fn update_config(lock: &mut CtrlKbdLed) -> Result<(), RogError> { @@ -127,13 +91,38 @@ impl<'a> CtrlKbdLedTask<'a> { } #[async_trait] -impl<'a> CtrlTask for CtrlKbdLedTask<'a> { - async fn do_task(&self) -> Result<(), RogError> { - self._manager.receive_prepare_for_sleep()?.next(); +impl CtrlTask for CtrlKbdLedTask { + async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + let connection = Connection::system() + .await + .expect("CtrlKbdLedTask could not create dbus connection"); - if let Ok(ref mut lock) = self.inner.try_lock() { - return Self::update_config(lock); - } + let manager = ManagerProxy::new(&connection) + .await + .expect("CtrlKbdLedTask could not create ManagerProxy"); + + let inner = self.inner.clone(); + executor + .spawn(async move { + if let Ok(p) = manager.receive_prepare_for_sleep().await { + p.for_each(|_| { + if let Ok(_lock) = inner.clone().try_lock() { + info!("CtrlKbdLedTask received sleep event (this feature is not yet complete)"); + // lock.config.system + } + }) + .await; + } + }) + .detach(); + + let inner = self.inner.clone(); + self.repeating_task(500, executor, move || { + if let Ok(ref mut lock) = inner.try_lock() { + Self::update_config(lock).unwrap(); + } + }) + .await; Ok(()) } } diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index eb96e82a..52c6fafe 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -7,6 +7,7 @@ use log::{info, warn}; use rog_profiles::error::ProfileError; use rog_profiles::{FanCurveProfiles, Profile}; use rog_supported::PlatformProfileFunctions; +use smol::Executor; use super::config::ProfileConfig; @@ -138,15 +139,19 @@ impl CtrlProfileTask { #[async_trait] impl CtrlTask for CtrlProfileTask { - async fn do_task(&self) -> Result<(), RogError> { - if let Ok(ref mut lock) = self.ctrl.try_lock() { - let new_profile = Profile::get_active_profile().unwrap(); - if new_profile != lock.config.active_profile { - lock.config.active_profile = new_profile; - lock.write_profile_curve_to_platform()?; - lock.save_config(); + async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + let ctrl = self.ctrl.clone(); + self.repeating_task(666, executor, move || { + if let Ok(ref mut lock) = ctrl.try_lock() { + let new_profile = Profile::get_active_profile().unwrap(); + if new_profile != lock.config.active_profile { + lock.config.active_profile = new_profile; + lock.write_profile_curve_to_platform().unwrap(); + lock.save_config(); + } } - } + }) + .await; Ok(()) } } diff --git a/daemon/src/ctrl_profiles/zbus.rs b/daemon/src/ctrl_profiles/zbus.rs index 7cfe4eed..3ea9a793 100644 --- a/daemon/src/ctrl_profiles/zbus.rs +++ b/daemon/src/ctrl_profiles/zbus.rs @@ -3,6 +3,7 @@ use log::warn; use rog_profiles::fan_curve_set::CurveData; use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::Profile; +use smol::Executor; use zbus::Connection; use zbus::SignalContext; @@ -203,15 +204,19 @@ impl crate::ZbusAdd for ProfileZbus { #[async_trait] impl CtrlTask for ProfileZbus { - async fn do_task(&self) -> Result<(), RogError> { - if let Ok(ref mut lock) = self.inner.try_lock() { - let new_profile = Profile::get_active_profile().unwrap(); - if new_profile != lock.config.active_profile { - lock.config.active_profile = new_profile; - lock.write_profile_curve_to_platform()?; - lock.save_config(); + async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { + let inner = self.inner.clone(); + self.repeating_task(500, executor, move || { + if let Ok(ref mut lock) = inner.try_lock() { + let new_profile = Profile::get_active_profile().unwrap(); + if new_profile != lock.config.active_profile { + lock.config.active_profile = new_profile; + lock.write_profile_curve_to_platform().unwrap(); + lock.save_config(); + } } - } + }) + .await; Ok(()) } } diff --git a/daemon/src/daemon.rs b/daemon/src/daemon.rs index d808f7df..0cc0fc28 100644 --- a/daemon/src/daemon.rs +++ b/daemon/src/daemon.rs @@ -2,9 +2,9 @@ use std::env; use std::error::Error; use std::io::Write; use std::sync::{Arc, Mutex}; -use std::time::Duration; use ::zbus::Connection; +use daemon::ctrl_profiles::controller::CtrlProfileTask; use log::LevelFilter; use log::{error, info, warn}; use smol::Executor; @@ -115,9 +115,13 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> .unwrap_or_else(|err| warn!("Profile control: {}", err)); let tmp = Arc::new(Mutex::new(ctrl)); - ProfileZbus::new(tmp.clone()) - .add_to_server(&mut connection) - .await; + let task = CtrlProfileTask::new(tmp.clone()); + task.create_task(executor).await.ok(); + + let task = ProfileZbus::new(tmp.clone()); + task.create_task(executor).await.ok(); + + task.add_to_server(&mut connection).await; } Err(err) => { error!("Profile control: {}", err); @@ -139,12 +143,8 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> let zbus = CtrlAnimeZbus(inner.clone()); zbus.add_to_server(&mut connection).await; - let task = CtrlAnimeTask::new(inner); - executor - .spawn(async move { - task.do_task().await.ok(); - }) - .detach(); + let task = CtrlAnimeTask::new(inner).await; + task.create_task(executor).await.ok(); } Err(err) => { error!("AniMe control: {}", err); @@ -167,11 +167,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> .await; let task = CtrlKbdLedTask::new(inner); - executor - .spawn(async move { - task.do_task().await.ok(); - }) - .detach(); + task.create_task(executor).await.ok(); } Err(err) => { error!("Keyboard control: {}", err); @@ -180,10 +176,8 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box> // Request dbus name after finishing initalizing all functions connection.request_name(DBUS_NAME).await?; - - // Loop to check errors and iterate zbus server + dbg!(); loop { - // Nothing to do here really - std::thread::sleep(Duration::from_millis(1)); + smol::block_on(executor.tick()); } } diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 6311b03d..f28fed00 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -29,9 +29,12 @@ pub mod ctrl_supported; pub mod error; +use std::time::Duration; + use crate::error::RogError; use async_trait::async_trait; use config::Config; +use smol::{stream::StreamExt, Executor, Timer}; use zbus::Connection; pub static VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -45,9 +48,25 @@ pub trait ZbusAdd { async fn add_to_server(self, server: &mut Connection); } +/// Set up a task to run on the async executor #[async_trait] pub trait CtrlTask { - async fn do_task(&self) -> Result<(), RogError>; + async fn create_task(&self, executor: &mut Executor) -> Result<(), RogError>; + + /// Create a timed repeating task + async fn repeating_task( + &self, + millis: u64, + executor: &mut Executor, + mut task: impl FnMut() + Send + 'static, + ) { + let timer = Timer::interval(Duration::from_millis(millis)); + executor + .spawn(async move { + timer.for_each(|_| task()).await; + }) + .detach(); + } } pub trait CtrlTaskComplex { diff --git a/design-patterns.md b/design-patterns.md index 7f1e57ff..3a091ab1 100644 --- a/design-patterns.md +++ b/design-patterns.md @@ -34,7 +34,7 @@ The task trait: pub struct CtrlAnimeTask(Arc>); impl crate::CtrlTask for CtrlAnimeTask { - fn do_task(&self) -> Result<(), RogError> { + fn create_task(&self, executor: &mut Executor) -> Result<(), RogError> { if let Ok(lock) = self.inner.try_lock() { }