Use tokio in asusctl

This commit is contained in:
Luke D. Jones
2022-09-22 22:36:16 +12:00
parent 3b9cf474a7
commit 9608d190b9
15 changed files with 148 additions and 209 deletions

View File

@@ -4,16 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased - 4.4.1] ## [Unreleased - 4.5.0]
### Added ### Added
- intofy watches on: - intofy watches on:
- `charge_control_end_threshold` - `charge_control_end_threshold`
- `panel_od` - `panel_od`
- `gpu_mux_mode` - `gpu_mux_mode`
- `platform_profile` - `platform_profile`
- keyboard brightness
- These allow for updating any associated config and sending dbus notifications. - These allow for updating any associated config and sending dbus notifications.
### Changed ### Changed
- Use loops to ensure that mutex is gained for LED changes. - Use loops to ensure that mutex is gained for LED changes.
- asusctl now uses tokio for async runtime. This helps simplify some code.
### Breaking ### Breaking
- DBUS: all charge control methods renamed: - DBUS: all charge control methods renamed:
- `ChargeControlEndThreshold` - `ChargeControlEndThreshold`

26
Cargo.lock generated
View File

@@ -588,8 +588,8 @@ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"smol",
"sysfs-class", "sysfs-class",
"tokio",
"toml", "toml",
"zbus", "zbus",
"zvariant", "zvariant",
@@ -1705,6 +1705,16 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "num_enum" name = "num_enum"
version = "0.5.7" version = "0.5.7"
@@ -2537,11 +2547,25 @@ dependencies = [
"autocfg", "autocfg",
"libc", "libc",
"mio", "mio",
"num_cpus",
"once_cell",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio-macros",
"winapi", "winapi",
] ]
[[package]]
name = "tokio-macros"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.9" version = "0.5.9"

View File

@@ -25,7 +25,7 @@ rog_profiles = { path = "../rog-profiles" }
rog_dbus = { path = "../rog-dbus" } rog_dbus = { path = "../rog-dbus" }
async-trait = "^0.1" async-trait = "^0.1"
smol = "^1.2" tokio = { version = "^1.21.1", features = ["macros", "rt-multi-thread", "time"]}
# cli and logging # cli and logging
log = "^0.4" log = "^0.4"

View File

@@ -13,7 +13,6 @@ use rog_anime::{
ActionData, AnimeDataBuffer, AnimePacketType, AnimeType, ActionData, AnimeDataBuffer, AnimePacketType, AnimeType,
}; };
use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw}; use rog_platform::{hid_raw::HidRaw, supported::AnimeSupportedFunctions, usb_raw::USBRaw};
use smol::Executor;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::{ use std::{
convert::TryFrom, convert::TryFrom,
@@ -230,11 +229,7 @@ impl CtrlAnimeTask {
#[async_trait] #[async_trait]
impl crate::CtrlTask for CtrlAnimeTask { impl crate::CtrlTask for CtrlAnimeTask {
async fn create_tasks<'a>( async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
&self,
executor: &mut Executor<'a>,
_: SignalContext<'a>,
) -> Result<(), RogError> {
let run_action = let run_action =
|start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| { |start: bool, lock: MutexGuard<CtrlAnime>, inner: Arc<Mutex<CtrlAnime>>| {
if start { if start {
@@ -251,7 +246,6 @@ impl crate::CtrlTask for CtrlAnimeTask {
let inner3 = self.inner.clone(); let inner3 = self.inner.clone();
let inner4 = self.inner.clone(); let inner4 = self.inner.clone();
self.create_sys_event_tasks( self.create_sys_event_tasks(
executor,
// Loop is required to try an attempt to get the mutex *without* blocking // Loop is required to try an attempt to get the mutex *without* blocking
// other threads - it is possible to end up with deadlocks otherwise. // other threads - it is possible to end up with deadlocks otherwise.
move || loop { move || loop {

View File

@@ -114,7 +114,7 @@ impl From<&AuraPowerConfig> for AuraPowerDev {
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
#[serde(default)] // #[serde(default)]
pub struct AuraConfig { pub struct AuraConfig {
pub brightness: LedBrightness, pub brightness: LedBrightness,
pub current_mode: AuraModeNum, pub current_mode: AuraModeNum,
@@ -271,7 +271,7 @@ impl AuraConfig {
if l == 0 { if l == 0 {
warn!("File is empty {}", AURA_CONFIG_PATH); warn!("File is empty {}", AURA_CONFIG_PATH);
} else { } else {
let x: AuraConfig = serde_json::from_str(&buf) let x = serde_json::from_str(&buf)
.unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH)); .unwrap_or_else(|_| panic!("Could not deserialise {}", AURA_CONFIG_PATH));
*self = x; *self = x;
} }

View File

@@ -11,12 +11,11 @@ use rog_aura::{
}; };
use rog_aura::{AuraZone, Direction, Speed, GRADIENT}; use rog_aura::{AuraZone, Direction, Speed, GRADIENT};
use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions}; use rog_platform::{hid_raw::HidRaw, keyboard_led::KeyboardLed, supported::LedSupportedFunctions};
use smol::Executor;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::MutexGuard; use std::sync::MutexGuard;
use zbus::SignalContext; use zbus::{export::futures_util::StreamExt, SignalContext};
use crate::GetSupported; use crate::GetSupported;
@@ -95,11 +94,7 @@ impl CtrlKbdLedTask {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlKbdLedTask { impl CtrlTask for CtrlKbdLedTask {
async fn create_tasks<'a>( async fn create_tasks(&self, _: SignalContext<'static>) -> Result<(), RogError> {
&self,
executor: &mut Executor<'a>,
_: SignalContext<'a>,
) -> Result<(), RogError> {
let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| { let load_save = |start: bool, mut lock: MutexGuard<CtrlKbdLed>| {
// If waking up // If waking up
if !start { if !start {
@@ -123,7 +118,6 @@ impl CtrlTask for CtrlKbdLedTask {
let inner3 = self.inner.clone(); let inner3 = self.inner.clone();
let inner4 = self.inner.clone(); let inner4 = self.inner.clone();
self.create_sys_event_tasks( self.create_sys_event_tasks(
executor,
// Loop so that we do aquire the lock but also don't block other // Loop so that we do aquire the lock but also don't block other
// threads (prevents potential deadlocks) // threads (prevents potential deadlocks)
move || loop { move || loop {
@@ -156,20 +150,18 @@ impl CtrlTask for CtrlKbdLedTask {
let ctrl2 = self.inner.clone(); let ctrl2 = self.inner.clone();
if let Ok(ctrl) = self.inner.lock() { if let Ok(ctrl) = self.inner.lock() {
let mut watch = ctrl.kd_brightness.monitor_brightness()?; let mut watch = ctrl.kd_brightness.monitor_brightness()?;
executor tokio::spawn(async move {
.spawn(async move { let mut buffer = [0; 32];
let mut buffer = [0; 1024]; watch
loop { .event_stream(&mut buffer)
if let Ok(events) = watch.read_events_blocking(&mut buffer) { .unwrap()
for _ in events { .for_each(|_| async {
if let Ok(lock) = ctrl2.try_lock() { if let Ok(lock) = ctrl2.try_lock() {
load_save(true, lock); load_save(true, lock);
} }
}
}
}
}) })
.detach(); .await;
});
} }
Ok(()) Ok(())

View File

@@ -4,7 +4,6 @@ use async_trait::async_trait;
use log::{info, warn}; use log::{info, warn};
use rog_platform::platform::{AsusPlatform, GpuMode}; use rog_platform::platform::{AsusPlatform, GpuMode};
use rog_platform::supported::RogBiosSupportedFunctions; use rog_platform::supported::RogBiosSupportedFunctions;
use smol::Executor;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::Path; use std::path::Path;
@@ -129,7 +128,7 @@ impl CtrlRogBios {
Ok(()) Ok(())
} }
fn set_panel_od(&self, enable: bool) -> Result<(), RogError> { fn set_panel_overdrive(&self, enable: bool) -> Result<(), RogError> {
self.platform.set_panel_od(enable).map_err(|err| { self.platform.set_panel_od(enable).map_err(|err| {
warn!("CtrlRogBios: set_panel_overdrive {}", err); warn!("CtrlRogBios: set_panel_overdrive {}", err);
err err
@@ -197,7 +196,7 @@ impl CtrlRogBios {
#[dbus_interface(signal)] #[dbus_interface(signal)]
async fn notify_post_boot_sound(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {} async fn notify_post_boot_sound(ctxt: &SignalContext<'_>, on: bool) -> zbus::Result<()> {}
async fn set_panel_overdrive( async fn set_panel_od(
&mut self, &mut self,
#[zbus(signal_context)] ctxt: SignalContext<'_>, #[zbus(signal_context)] ctxt: SignalContext<'_>,
overdrive: bool, overdrive: bool,
@@ -256,7 +255,7 @@ impl crate::Reloadable for CtrlRogBios {
} else { } else {
false false
}; };
self.set_panel_od(p)?; self.set_panel_overdrive(p)?;
} }
Ok(()) Ok(())
} }
@@ -269,22 +268,17 @@ impl CtrlRogBios {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlRogBios { impl CtrlTask for CtrlRogBios {
async fn create_tasks<'a>( async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
&self,
executor: &mut Executor<'a>,
signal_ctxt: SignalContext<'a>,
) -> Result<(), RogError> {
let platform1 = self.clone(); let platform1 = self.clone();
let platform2 = self.clone(); let platform2 = self.clone();
self.create_sys_event_tasks( self.create_sys_event_tasks(
executor,
move || {}, move || {},
move || { move || {
info!("CtrlRogBios reloading panel_od"); info!("CtrlRogBios reloading panel_od");
if let Ok(lock) = platform1.config.try_lock() { if let Ok(lock) = platform1.config.try_lock() {
if platform1.platform.has_panel_od() { if platform1.platform.has_panel_od() {
platform1 platform1
.set_panel_od(lock.panel_od) .set_panel_overdrive(lock.panel_od)
.map_err(|err| { .map_err(|err| {
warn!("CtrlCharge: set_limit {}", err); warn!("CtrlCharge: set_limit {}", err);
err err
@@ -299,7 +293,7 @@ impl CtrlTask for CtrlRogBios {
if let Ok(lock) = platform2.config.try_lock() { if let Ok(lock) = platform2.config.try_lock() {
if platform2.platform.has_panel_od() { if platform2.platform.has_panel_od() {
platform2 platform2
.set_panel_od(lock.panel_od) .set_panel_overdrive(lock.panel_od)
.map_err(|err| { .map_err(|err| {
warn!("CtrlCharge: set_limit {}", err); warn!("CtrlCharge: set_limit {}", err);
err err
@@ -311,9 +305,8 @@ impl CtrlTask for CtrlRogBios {
) )
.await; .await;
self.watch_panel_od(executor, signal_ctxt.clone()).await?; self.watch_panel_od(signal_ctxt.clone()).await?;
self.watch_gpu_mux_mode(executor, signal_ctxt.clone()) self.watch_gpu_mux_mode(signal_ctxt.clone()).await?;
.await?;
Ok(()) Ok(())
} }

View File

@@ -4,7 +4,6 @@ use async_trait::async_trait;
use log::{info, warn}; use log::{info, warn};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use rog_platform::supported::ChargeSupportedFunctions; use rog_platform::supported::ChargeSupportedFunctions;
use smol::Executor;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use zbus::dbus_interface; use zbus::dbus_interface;
@@ -62,12 +61,11 @@ impl CtrlPower {
err err
}) })
.unwrap_or(100); .unwrap_or(100);
self.set(limit) if let Ok(mut config) = self.config.try_lock() {
.map_err(|err| { config.read();
warn!("CtrlCharge: set_limit {}", err); config.bat_charge_limit = limit;
err config.write();
}) }
.ok();
return config.bat_charge_limit; return config.bat_charge_limit;
} }
@@ -129,15 +127,10 @@ impl CtrlPower {
#[async_trait] #[async_trait]
impl CtrlTask for CtrlPower { impl CtrlTask for CtrlPower {
async fn create_tasks<'a>( async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
&self,
executor: &mut Executor<'a>,
signal_ctxt: SignalContext<'a>,
) -> Result<(), RogError> {
let power1 = self.clone(); let power1 = self.clone();
let power2 = self.clone(); let power2 = self.clone();
self.create_sys_event_tasks( self.create_sys_event_tasks(
executor,
move || {}, move || {},
move || { move || {
info!("CtrlCharge reloading charge limit"); info!("CtrlCharge reloading charge limit");
@@ -167,8 +160,7 @@ impl CtrlTask for CtrlPower {
) )
.await; .await;
self.watch_charge_control_end_threshold(executor, signal_ctxt) self.watch_charge_control_end_threshold(signal_ctxt).await?;
.await?;
Ok(()) Ok(())
} }

View File

@@ -6,7 +6,7 @@ use rog_profiles::fan_curve_set::CurveData;
use rog_profiles::fan_curve_set::FanCurveSet; use rog_profiles::fan_curve_set::FanCurveSet;
use rog_profiles::Profile; use rog_profiles::Profile;
use rog_profiles::PLATFORM_PROFILE; use rog_profiles::PLATFORM_PROFILE;
use smol::Executor; use zbus::export::futures_util::StreamExt;
use zbus::Connection; use zbus::Connection;
use zbus::SignalContext; use zbus::SignalContext;
@@ -219,21 +219,18 @@ impl crate::ZbusAdd for ProfileZbus {
#[async_trait] #[async_trait]
impl CtrlTask for ProfileZbus { impl CtrlTask for ProfileZbus {
async fn create_tasks<'a>( async fn create_tasks(&self, signal_ctxt: SignalContext<'static>) -> Result<(), RogError> {
&self,
executor: &mut Executor<'a>,
signal_ctxt: SignalContext<'a>,
) -> Result<(), RogError> {
let ctrl = self.inner.clone(); let ctrl = self.inner.clone();
let mut inotify = Inotify::init()?; let mut watch = Inotify::init()?;
inotify.add_watch(PLATFORM_PROFILE, WatchMask::MODIFY)?; watch.add_watch(PLATFORM_PROFILE, WatchMask::CLOSE_WRITE)?;
executor tokio::spawn(async move {
.spawn(async move { let mut buffer = [0; 32];
let mut buffer = [0; 1024];
loop { loop {
if let Ok(events) = inotify.read_events_blocking(&mut buffer) { watch
for _ in events { .event_stream(&mut buffer)
.unwrap()
.for_each(|_| async {
let mut active_profile = None; let mut active_profile = None;
if let Ok(ref mut lock) = ctrl.try_lock() { if let Ok(ref mut lock) = ctrl.try_lock() {
@@ -247,15 +244,14 @@ impl CtrlTask for ProfileZbus {
} }
if let Some(active_profile) = active_profile { if let Some(active_profile) = active_profile {
Self::notify_profile(&signal_ctxt, active_profile) Self::notify_profile(&signal_ctxt.clone(), active_profile)
.await .await
.ok(); .ok();
} }
}
}
}
}) })
.detach(); .await;
}
});
Ok(()) Ok(())
} }

View File

@@ -2,11 +2,12 @@ use std::env;
use std::error::Error; use std::error::Error;
use std::io::Write; use std::io::Write;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration;
use ::zbus::{Connection, SignalContext}; use ::zbus::{Connection, SignalContext};
use log::LevelFilter; use log::LevelFilter;
use log::{error, info, warn}; use log::{error, info, warn};
use smol::Executor; use tokio::time::sleep;
use daemon::ctrl_anime::config::AnimeConfig; use daemon::ctrl_anime::config::AnimeConfig;
use daemon::ctrl_anime::zbus::CtrlAnimeZbus; use daemon::ctrl_anime::zbus::CtrlAnimeZbus;
@@ -31,7 +32,8 @@ use rog_profiles::Profile;
static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf"; static PROFILE_CONFIG_PATH: &str = "/etc/asusd/profile.conf";
pub fn main() -> Result<(), Box<dyn std::error::Error>> { #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = env_logger::Builder::new(); let mut logger = env_logger::Builder::new();
logger logger
.target(env_logger::Target::Stdout) .target(env_logger::Target::Stdout)
@@ -60,14 +62,12 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
info!(" rog-profiles v{}", rog_profiles::VERSION); info!(" rog-profiles v{}", rog_profiles::VERSION);
info!("rog-platform v{}", rog_platform::VERSION); info!("rog-platform v{}", rog_platform::VERSION);
let mut executor = Executor::new(); start_daemon().await?;
smol::block_on(start_daemon(&mut executor))?;
Ok(()) Ok(())
} }
/// The actual main loop for the daemon /// The actual main loop for the daemon
async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>> { async fn start_daemon() -> Result<(), Box<dyn Error>> {
let supported = SupportedFunctions::get_supported(); let supported = SupportedFunctions::get_supported();
print_board_info(); print_board_info();
println!("{}", serde_json::to_string_pretty(&supported)?); println!("{}", serde_json::to_string_pretty(&supported)?);
@@ -90,7 +90,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
let task = CtrlRogBios::new(config.clone())?; let task = CtrlRogBios::new(config.clone())?;
let sig = SignalContext::new(&connection, "/org/asuslinux/Platform")?; let sig = SignalContext::new(&connection, "/org/asuslinux/Platform")?;
task.create_tasks(executor, sig).await.ok(); task.create_tasks(sig).await.ok();
} }
Err(err) => { Err(err) => {
error!("rog_bios_control: {}", err); error!("rog_bios_control: {}", err);
@@ -107,7 +107,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
let task = CtrlPower::new(config)?; let task = CtrlPower::new(config)?;
let sig = SignalContext::new(&connection, "/org/asuslinux/Charge")?; let sig = SignalContext::new(&connection, "/org/asuslinux/Charge")?;
task.create_tasks(executor, sig).await.ok(); task.create_tasks(sig).await.ok();
} }
Err(err) => { Err(err) => {
error!("charge_control: {}", err); error!("charge_control: {}", err);
@@ -127,7 +127,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
let sig = SignalContext::new(&connection, "/org/asuslinux/Profile")?; let sig = SignalContext::new(&connection, "/org/asuslinux/Profile")?;
let task = ProfileZbus::new(tmp.clone()); let task = ProfileZbus::new(tmp.clone());
task.create_tasks(executor, sig).await.ok(); task.create_tasks(sig).await.ok();
task.add_to_server(&mut connection).await; task.add_to_server(&mut connection).await;
} }
Err(err) => { Err(err) => {
@@ -152,7 +152,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
let task = CtrlAnimeTask::new(inner).await; let task = CtrlAnimeTask::new(inner).await;
let sig = SignalContext::new(&connection, "/org/asuslinux/Anime")?; let sig = SignalContext::new(&connection, "/org/asuslinux/Anime")?;
task.create_tasks(executor, sig).await.ok(); task.create_tasks(sig).await.ok();
} }
Err(err) => { Err(err) => {
error!("AniMe control: {}", err); error!("AniMe control: {}", err);
@@ -176,7 +176,7 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
let task = CtrlKbdLedTask::new(inner); let task = CtrlKbdLedTask::new(inner);
let sig = SignalContext::new(&connection, "/org/asuslinux/Aura")?; let sig = SignalContext::new(&connection, "/org/asuslinux/Aura")?;
task.create_tasks(executor, sig).await.ok(); task.create_tasks(sig).await.ok();
} }
Err(err) => { Err(err) => {
error!("Keyboard control: {}", err); error!("Keyboard control: {}", err);
@@ -185,7 +185,9 @@ async fn start_daemon(executor: &mut Executor<'_>) -> Result<(), Box<dyn Error>>
// Request dbus name after finishing initalizing all functions // Request dbus name after finishing initalizing all functions
connection.request_name(DBUS_NAME).await?; connection.request_name(DBUS_NAME).await?;
loop { loop {
smol::block_on(executor.tick()); // This is just a blocker to idle and ensure the reator reacts
sleep(Duration::from_millis(1000)).await;
} }
} }

View File

@@ -23,12 +23,10 @@ use std::time::Duration;
use crate::error::RogError; use crate::error::RogError;
use async_trait::async_trait; use async_trait::async_trait;
use config::Config;
use inotify::{Inotify, WatchMask};
use log::warn; use log::warn;
use logind_zbus::manager::ManagerProxy; use logind_zbus::manager::ManagerProxy;
use smol::{stream::StreamExt, Executor, Timer}; use tokio::time;
use zbus::{Connection, SignalContext}; use zbus::{export::futures_util::StreamExt, Connection, SignalContext};
use zvariant::ObjectPath; use zvariant::ObjectPath;
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -65,6 +63,8 @@ pub trait ZbusAdd {
/// - `notify_<name>(SignalContext, SomeValue)` /// - `notify_<name>(SignalContext, SomeValue)`
/// ///
/// In most cases if `SomeValue` is stored in a config then `<name>()` getter is expected to update it. /// In most cases if `SomeValue` is stored in a config then `<name>()` getter is expected to update it.
/// The getter should *never* write back to the path or attribute that is being watched or an
/// infinite loop will occur.
/// ///
/// # Example /// # Example
/// ///
@@ -78,28 +78,24 @@ pub trait ZbusAdd {
macro_rules! task_watch_item { macro_rules! task_watch_item {
($name:ident $self_inner:ident) => { ($name:ident $self_inner:ident) => {
concat_idents::concat_idents!(fn_name = watch_, $name { concat_idents::concat_idents!(fn_name = watch_, $name {
async fn fn_name<'a>( async fn fn_name(
&self, &self,
executor: &mut Executor<'a>, signal_ctxt: SignalContext<'static>,
signal_ctxt: SignalContext<'a>,
) -> Result<(), RogError> { ) -> Result<(), RogError> {
use zbus::export::futures_util::StreamExt; use zbus::export::futures_util::StreamExt;
let ctrl = self.clone(); let ctrl = self.clone();
concat_idents::concat_idents!(watch_fn = monitor_, $name { concat_idents::concat_idents!(watch_fn = monitor_, $name {
let mut watch = self.$self_inner.watch_fn()?; let mut watch = self.$self_inner.watch_fn()?;
executor tokio::spawn(async move {
.spawn(async move { let mut buffer = [0; 32];
let mut buffer = [0; 1024];
watch.event_stream(&mut buffer).unwrap().for_each(|_| async { watch.event_stream(&mut buffer).unwrap().for_each(|_| async {
let value = ctrl.$name(); let value = ctrl.$name();
dbg!(value);
concat_idents::concat_idents!(notif_fn = notify_, $name { concat_idents::concat_idents!(notif_fn = notify_, $name {
Self::notif_fn(&signal_ctxt, value).await.unwrap(); Self::notif_fn(&signal_ctxt, value).await.unwrap();
}); });
}).await; }).await;
}) });
.detach();
}); });
Ok(()) Ok(())
} }
@@ -112,59 +108,23 @@ macro_rules! task_watch_item {
pub trait CtrlTask { pub trait CtrlTask {
/// Implement to set up various tasks that may be required, using the `Executor`. /// Implement to set up various tasks that may be required, using the `Executor`.
/// No blocking loops are allowed, or they must be run on a separate thread. /// No blocking loops are allowed, or they must be run on a separate thread.
async fn create_tasks<'a>( async fn create_tasks(&self, signal: SignalContext<'static>) -> Result<(), RogError>;
&self,
executor: &mut Executor<'a>,
signal: SignalContext<'a>,
) -> Result<(), RogError>;
/// Free method to run a task when the path is modified
///
/// Not very useful if you need to also do a zbus notification.
fn create_tasks_inotify(
&self,
executor: &mut Executor,
path: &str,
mut task: impl FnMut() + Send + 'static,
) -> Result<(), RogError> {
let mut inotify = Inotify::init()?;
inotify.add_watch(path, WatchMask::MODIFY)?;
let mut buffer = [0; 1024];
executor
.spawn(async move {
loop {
if let Ok(events) = inotify.read_events_blocking(&mut buffer) {
for _ in events {
task()
}
}
}
})
.detach();
Ok(())
}
/// Create a timed repeating task /// Create a timed repeating task
async fn repeating_task( async fn repeating_task(&self, millis: u64, mut task: impl FnMut() + Send + 'static) {
&self, let mut timer = time::interval(Duration::from_millis(millis));
millis: u64, tokio::spawn(async move {
executor: &mut Executor, timer.tick().await;
mut task: impl FnMut() + Send + 'static, task();
) { });
let timer = Timer::interval(Duration::from_millis(millis));
executor
.spawn(async move {
timer.for_each(|_| task()).await;
})
.detach();
} }
/// Free helper method to create tasks to run on: sleep, wake, shutdown, boot /// Free helper method to create tasks to run on: sleep, wake, shutdown, boot
///
/// The closures can potentially block, so execution time should be the minimal possible
/// such as save a variable.
async fn create_sys_event_tasks( async fn create_sys_event_tasks(
&self, &self,
executor: &mut Executor,
mut on_sleep: impl FnMut() + Send + 'static, mut on_sleep: impl FnMut() + Send + 'static,
mut on_wake: impl FnMut() + Send + 'static, mut on_wake: impl FnMut() + Send + 'static,
mut on_shutdown: impl FnMut() + Send + 'static, mut on_shutdown: impl FnMut() + Send + 'static,
@@ -178,11 +138,9 @@ pub trait CtrlTask {
.await .await
.expect("Controller could not create ManagerProxy"); .expect("Controller could not create ManagerProxy");
executor tokio::spawn(async move {
.spawn(async move { if let Ok(mut notif) = manager.receive_prepare_for_sleep().await {
if let Ok(notif) = manager.receive_prepare_for_sleep().await { while let Some(event) = notif.next().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() { if let Ok(args) = event.args() {
if args.start { if args.start {
on_sleep(); on_sleep();
@@ -190,21 +148,17 @@ pub trait CtrlTask {
on_wake(); on_wake();
} }
} }
})
.await;
} }
}) }
.detach(); });
let manager = ManagerProxy::new(&connection) let manager = ManagerProxy::new(&connection)
.await .await
.expect("Controller could not create ManagerProxy"); .expect("Controller could not create ManagerProxy");
executor tokio::spawn(async move {
.spawn(async move { if let Ok(mut notif) = manager.receive_prepare_for_shutdown().await {
if let Ok(notif) = manager.receive_prepare_for_shutdown().await { while let Some(event) = notif.next().await {
notif
.for_each(|event| {
if let Ok(args) = event.args() { if let Ok(args) = event.args() {
if args.start { if args.start {
on_shutdown(); on_shutdown();
@@ -212,18 +166,10 @@ pub trait CtrlTask {
on_boot(); on_boot();
} }
} }
})
.await;
} }
})
.detach();
} }
} });
}
pub trait CtrlTaskComplex {
type A;
fn do_task(&mut self, config: &mut Config, event: Self::A);
} }
pub trait GetSupported { pub trait GetSupported {

View File

@@ -156,7 +156,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
start_closed = false; start_closed = false;
continue; continue;
} }
dbg!("asda");
} }
Ok(()) Ok(())
} }

View File

@@ -27,7 +27,7 @@ impl eframe::App for AppErrorShow {
.add(Button::new(RichText::new("Okay").size(20.0))) .add(Button::new(RichText::new("Okay").size(20.0)))
.clicked() .clicked()
{ {
frame.quit(); frame.close();
} }
}); });
}); });

View File

@@ -39,7 +39,7 @@ impl<'a> RogApp<'a> {
Button::new(RichText::new("").size(height - 4.0)).frame(false), Button::new(RichText::new("").size(height - 4.0)).frame(false),
); );
if close_response.clicked() { if close_response.clicked() {
frame.quit(); frame.close();
} }
}); });
}); });

View File

@@ -21,7 +21,6 @@ macro_rules! watch_attr {
pub fn fn_name(&self) -> Result<inotify::Inotify> { pub fn fn_name(&self) -> Result<inotify::Inotify> {
let mut path = self.$item.clone(); let mut path = self.$item.clone();
path.push($attr_name); path.push($attr_name);
dbg!(&path);
let mut inotify = inotify::Inotify::init().unwrap(); let mut inotify = inotify::Inotify::init().unwrap();
inotify.add_watch(path.to_str().unwrap(), inotify::WatchMask::MODIFY).unwrap(); inotify.add_watch(path.to_str().unwrap(), inotify::WatchMask::MODIFY).unwrap();
Ok(inotify) Ok(inotify)