Refactor API processing to apply settings from single thread and queue API calls instead of locking

This commit is contained in:
NGnius (Graham) 2022-11-09 22:09:05 -05:00
parent 357a7cfe37
commit 1610f18278
17 changed files with 822 additions and 452 deletions

33
backend/Cargo.lock generated
View file

@ -38,6 +38,28 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "async-recursion"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -567,12 +589,14 @@ dependencies = [
[[package]] [[package]]
name = "powertools-rs" name = "powertools-rs"
version = "1.0.5" version = "1.1.0"
dependencies = [ dependencies = [
"async-trait",
"log", "log",
"serde", "serde",
"serde_json", "serde_json",
"simplelog", "simplelog",
"tokio",
"usdpl-back", "usdpl-back",
] ]
@ -1053,12 +1077,15 @@ dependencies = [
[[package]] [[package]]
name = "usdpl-back" name = "usdpl-back"
version = "0.6.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbbc0781e83ba990f8239142e33173a2d2548701775f3db66702d1af4fd0319a" checksum = "4ca96dac4ee471e9534940f99cb36f5212cbfaf4e7779eb3ba970d3c511d9583"
dependencies = [ dependencies = [
"async-recursion",
"async-trait",
"bytes", "bytes",
"hex", "hex",
"log",
"obfstr", "obfstr",
"tokio", "tokio",
"usdpl-core", "usdpl-core",

View file

@ -1,15 +1,19 @@
[package] [package]
name = "powertools-rs" name = "powertools-rs"
version = "1.0.5" version = "1.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
usdpl-back = { version = "0.6.0", features = ["blocking"]} usdpl-back = { version = "0.7.0", features = ["blocking"]}
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
# async
tokio = { version = "*", features = ["time"] }
async-trait = { version = "0.1" }
# logging # logging
log = "0.4" log = "0.4"
simplelog = "0.12" simplelog = "0.12"

View file

@ -0,0 +1,65 @@
//use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
/*pub struct AsyncIsh<T: Send,
TS: (Fn(super::ApiParameterType) -> Result<T, String>) + Send + Sync,
SG: (Fn(T) -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> {
pub trans_setter: TS, // assumed to be pretty fast
pub set_get: SG, // probably has locks (i.e. slow)
pub trans_getter: TG, // assumed to be pretty fast
}
#[async_trait::async_trait]
impl <T: Send,
TS: (Fn(super::ApiParameterType) -> Result<T, String>) + Send + Sync,
SG: (Fn(T) -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync>
AsyncCallable for AsyncIsh<T, TS, SG, TG> {
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
let t_to_set = match (self.trans_setter)(params) {
Ok(t) => t,
Err(e) => return vec![e.into()]
};
let t_got = match tokio::task::spawn_blocking(|| (self.set_get)(t_to_set)).await {
Ok(t) => t,
Err(e) => return vec![e.to_string().into()],
};
(self.trans_getter)(t_got)
}
}*/
pub struct AsyncIshGetter<T: Send + 'static,
Gen: (Fn() -> G) + Send + Sync,
G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> {
pub set_get: Gen, // probably has locks (i.e. slow)
pub trans_getter: TG, // assumed to be pretty fast
}
#[async_trait::async_trait]
impl <T: Send + 'static,
Gen: (Fn() -> G) + Send + Sync,
G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync>
AsyncCallable for AsyncIshGetter<T, Gen, G, TG> {
async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType {
let getter = (self.set_get)();
let t_got = match tokio::task::spawn_blocking(move || getter()).await {
Ok(t) => t,
Err(e) => return vec![e.to_string().into()],
};
(self.trans_getter)(t_got)
}
}
pub struct Blocking<F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> {
pub func: F,
}
#[async_trait::async_trait]
impl <F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> AsyncCallable for Blocking<F> {
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
(self.func)(params)
}
}

View file

@ -1,8 +1,8 @@
use std::sync::{mpsc::Sender, Arc, Mutex}; use std::sync::mpsc::{Sender, self};
use std::sync::Mutex;
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use crate::settings::{Battery, OnSet}; use super::handler::{ApiMessage, BatteryMessage};
use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
/// Current current (ha!) web method /// Current current (ha!) web method
pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
@ -26,22 +26,18 @@ pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType {
/// Generate set battery charge rate web method /// Generate set battery charge rate web method
pub fn set_charge_rate( pub fn set_charge_rate(
settings: Arc<Mutex<Battery>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |rate: f64|
sender.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(rate as u64))))
.expect("set_charge_rate send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(new_val)) = params_in.get(0) { if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "battery"); setter(new_val);
settings_lock.charge_rate = Some(*new_val as _); vec![(new_val).into()]
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(
settings_lock.on_set(),
settings_lock.charge_rate.unwrap(),
)
} else { } else {
vec!["set_charge_rate missing parameter".into()] vec!["set_charge_rate missing parameter".into()]
} }
@ -50,30 +46,28 @@ pub fn set_charge_rate(
/// Generate get battery charge rate web method /// Generate get battery charge rate web method
pub fn get_charge_rate( pub fn get_charge_rate(
settings: Arc<Mutex<Battery>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |rate: Option<u64>| tx.send(rate).expect("get_charge_rate callback send failed");
sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeRate(Box::new(callback)))).expect("get_charge_rate send failed");
rx.recv().expect("get_charge_rate callback recv failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let settings_lock = unwrap_lock(settings.lock(), "battery"); vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
vec![settings_lock
.charge_rate
.map(|x| x.into())
.unwrap_or(Primitive::Empty)]
} }
} }
/// Generate unset battery charge rate web method /// Generate unset battery charge rate web method
pub fn unset_charge_rate( pub fn unset_charge_rate(
settings: Arc<Mutex<Battery>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
move |_: super::ApiParameterType| { let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeRate(None))).expect("unset_charge_rate send failed");
let mut settings_lock = unwrap_lock(settings.lock(), "battery"); move |_params_in: super::ApiParameterType| {
settings_lock.charge_rate = None; setter();
unwrap_maybe_fatal( vec![true.into()]
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(settings_lock.on_set(), true)
} }
} }

View file

@ -1,8 +1,11 @@
use std::sync::{mpsc::Sender, Arc, Mutex}; use std::sync::mpsc::{Sender, self};
use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
use crate::settings::{Cpu, OnSet, SettingError, SettingVariant, MinMax}; use crate::settings::{Cpu, SettingError, SettingVariant, MinMax};
use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use super::handler::{ApiMessage, CpuMessage};
/// Available CPUs web method /// Available CPUs web method
pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
@ -20,30 +23,22 @@ pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
/// Generate set CPU online web method /// Generate set CPU online web method
pub fn set_cpu_online( pub fn set_cpu_online(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: bool|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value))).expect("set_cpu_online send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); //let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
if let Some(cpu) = settings_lock.get_mut(*index as usize) { if let Some(&Primitive::Bool(online)) = params_in.get(1) {
if let Some(Primitive::Bool(online)) = params_in.get(1) { setter(index as usize, online);
cpu.online = *online; vec![online.into()]
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(
cpu.on_set(),
cpu.online,
)
} else { } else {
vec!["set_cpu_online missing parameter 1".into()] vec!["set_cpu_online missing parameter 1".into()]
} }
} else {
vec!["set_cpu_online cpu index out of bounds".into()]
}
} else { } else {
vec!["set_cpu_online missing parameter 0".into()] vec!["set_cpu_online missing parameter 0".into()]
} }
@ -51,82 +46,95 @@ pub fn set_cpu_online(
} }
pub fn set_cpus_online( pub fn set_cpus_online(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |values: Vec<bool>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values))).expect("set_cpus_online send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len()); let mut result = Vec::with_capacity(params_in.len());
let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); let mut values = Vec::with_capacity(params_in.len());
for i in 0..params_in.len() { for i in 0..params_in.len() {
if let Primitive::Bool(online) = params_in[i] { if let Primitive::Bool(online) = params_in[i] {
if let Some(cpu) = settings_lock.get_mut(i) { values.push(online);
cpu.online = online; result.push(online.into());
match cpu.on_set() {
Ok(_) => result.push(cpu.online.into()),
Err(e) => result.push(e.msg.into())
}
}
} else { } else {
values.push(true);
result.push(format!("Invalid parameter {}", i).into()) result.push(format!("Invalid parameter {}", i).into())
} }
} }
unwrap_maybe_fatal( setter(values);
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
result result
} }
} }
pub fn get_cpus_online( /*pub fn get_cpus_online(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("get_cpus_online callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed");
rx.recv().expect("get_cpus_online callback recv failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let settings_lock = unwrap_lock(settings.lock(), "cpu"); let result = getter();
let mut output = Vec::with_capacity(settings_lock.len()); let mut output = Vec::with_capacity(result.len());
for cpu in settings_lock.as_slice() { for &status in result.as_slice() {
output.push(cpu.online.into()); output.push(status.into());
} }
output output
} }
}*/
pub fn get_cpus_online(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("get_cpus_online callback send failed");
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed");
rx.recv().expect("get_cpus_online callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
let mut output = Vec::with_capacity(result.len());
for &status in result.as_slice() {
output.push(status.into());
}
output
}
}
} }
pub fn set_clock_limits( pub fn set_clock_limits(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: MinMax<u64>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, Some(value)))).expect("set_clock_limits send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); if let Some(&Primitive::F64(min)) = params_in.get(1) {
if let Some(cpu) = settings_lock.get_mut(*index as usize) { if let Some(&Primitive::F64(max)) = params_in.get(2) {
if let Some(Primitive::F64(min)) = params_in.get(1) { setter(index as usize, MinMax {min: min as u64, max: max as u64});
if let Some(Primitive::F64(max)) = params_in.get(2) { vec![min.into(), max.into()]
cpu.clock_limits = Some(MinMax {
min: *min as _,
max: *max as _,
});
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
match cpu.on_set() {
Ok(_) => vec![
cpu.clock_limits.as_ref().unwrap().min.into(),
cpu.clock_limits.as_ref().unwrap().max.into(),
],
Err(e) => vec![e.msg.into()]
}
} else { } else {
vec!["set_clock_limits missing parameter 2".into()] vec!["set_clock_limits missing parameter 2".into()]
} }
} else { } else {
vec!["set_clock_limits missing parameter 1".into()] vec!["set_clock_limits missing parameter 1".into()]
} }
} else {
vec!["set_clock_limits cpu index out of bounds".into()]
}
} else { } else {
vec!["set_clock_limits missing parameter 0".into()] vec!["set_clock_limits missing parameter 0".into()]
} }
@ -134,20 +142,22 @@ pub fn set_clock_limits(
} }
pub fn get_clock_limits( pub fn get_clock_limits(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move |index: usize| {
let (tx, rx) = mpsc::channel();
let callback = move |values: Option<MinMax<u64>>| tx.send(values).expect("get_clock_limits callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetClockLimits(index, Box::new(callback)))).expect("get_clock_limits send failed");
rx.recv().expect("get_clock_limits callback recv failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); if let Some(min_max) = getter(index as usize) {
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
if let Some(min_max) = &cpu.clock_limits {
vec![min_max.min.into(), min_max.max.into()] vec![min_max.min.into(), min_max.max.into()]
} else { } else {
vec![Primitive::Empty, Primitive::Empty] vec![Primitive::Empty, Primitive::Empty]
} }
} else {
vec!["get_clock_limits cpu index out of bounds".into()]
}
} else { } else {
vec!["get_clock_limits missing parameter 0".into()] vec!["get_clock_limits missing parameter 0".into()]
} }
@ -155,23 +165,17 @@ pub fn get_clock_limits(
} }
pub fn unset_clock_limits( pub fn unset_clock_limits(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None))).expect("unset_clock_limits send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); setter(index as usize);
if let Some(cpu) = settings_lock.get_mut(*index as usize) { vec![true.into()]
cpu.clock_limits = None;
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(cpu.on_set(), true)
} else {
vec!["get_clock_limits cpu index out of bounds".into()]
}
} else { } else {
vec!["get_clock_limits missing parameter 0".into()] vec!["get_clock_limits missing parameter 0".into()]
} }
@ -179,44 +183,67 @@ pub fn unset_clock_limits(
} }
pub fn set_cpu_governor( pub fn set_cpu_governor(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, governor: String|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor))).expect("set_cpu_governor send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
if let Some(cpu) = settings_lock.get_mut(*index as usize) {
if let Some(Primitive::String(governor)) = params_in.get(1) { if let Some(Primitive::String(governor)) = params_in.get(1) {
cpu.governor = governor.to_owned(); setter(index as usize, governor.to_owned());
unwrap_maybe_fatal( vec![(governor as &str).into()]
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(
cpu.on_set(),
&cpu.governor as &str,
)
} else { } else {
vec!["set_cpu_governor missing parameter 1".into()] vec!["set_cpu_governor missing parameter 1".into()]
} }
} else {
vec!["set_cpu_governor cpu index out of bounds".into()]
}
} else { } else {
vec!["set_cpu_governor missing parameter 0".into()] vec!["set_cpu_governor missing parameter 0".into()]
} }
} }
} }
pub fn get_cpu_governors( pub fn set_cpus_governors(
settings: Arc<Mutex<Vec<Cpu>>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |governors: Vec<String>|
sender.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors))).expect("set_cpus_governor send failed");
move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len());
let mut values = Vec::with_capacity(params_in.len());
for i in 0..params_in.len() {
if let Primitive::String(gov) = &params_in[i] {
values.push(gov.to_owned());
result.push((gov as &str).into());
} else {
//values.push(true);
result.push(format!("Invalid parameter {}", i).into())
}
}
setter(values);
result
}
}
pub fn get_cpu_governors(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<String>| tx.send(values).expect("get_cpu_governors callback send failed");
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(callback)))).expect("get_cpu_governors send failed");
rx.recv().expect("get_cpu_governors callback recv failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let settings_lock = unwrap_lock(settings.lock(), "cpu"); let result = getter();
let mut output = Vec::with_capacity(settings_lock.len()); let mut output = Vec::with_capacity(result.len());
for cpu in settings_lock.as_slice() { for cpu in result.as_slice() {
output.push(cpu.governor.clone().into()); output.push(cpu.clone().into());
} }
output output
} }

View file

@ -1,29 +1,25 @@
use std::sync::{mpsc::Sender, Arc, Mutex}; use std::sync::mpsc::{Sender, self};
use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
use crate::settings::{General, Settings, OnSet}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, GeneralMessage};
/// Generate set persistent web method /// Generate set persistent web method
pub fn set_persistent( pub fn set_persistent(
settings: Arc<Mutex<General>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |pers: bool|
sender.lock()
.unwrap()
.send(ApiMessage::General(GeneralMessage::SetPersistent(pers))).expect("set_persistent send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::Bool(new_val)) = params_in.get(0) { if let Some(&Primitive::Bool(new_val)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "general"); setter(new_val);
settings_lock.persistent = *new_val; //log::debug!("Persistent is now {}", settings_lock.persistent);
unwrap_maybe_fatal( vec![new_val.into()]
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
let result = super::utility::map_empty_result(
settings_lock.on_set(),
settings_lock.persistent,
);
log::debug!("Persistent is now {}", settings_lock.persistent);
result
} else { } else {
vec!["set_persistent missing parameter".into()] vec!["set_persistent missing parameter".into()]
} }
@ -32,30 +28,34 @@ pub fn set_persistent(
/// Generate get persistent save mode web method /// Generate get persistent save mode web method
pub fn get_persistent( pub fn get_persistent(
settings: Arc<Mutex<General>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |value: bool| tx.send(value).expect("get_persistent callback send failed");
sender.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetPersistent(Box::new(callback)))).expect("get_persistent send failed");
rx.recv().expect("get_persistent callback recv failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let settings_lock = unwrap_lock(settings.lock(), "general"); vec![getter().into()]
vec![settings_lock
.persistent.into()]
} }
} }
/// Generate load app settings from file web method /// Generate load app settings from file web method
pub fn load_settings( pub fn load_settings(
settings: Settings, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |path: String, name: String|
sender.lock()
.unwrap()
.send(ApiMessage::LoadSettings(path, name)).expect("load_settings send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::String(path)) = params_in.get(0) { if let Some(Primitive::String(path)) = params_in.get(0) {
if let Some(Primitive::String(name)) = params_in.get(1) { if let Some(Primitive::String(name)) = params_in.get(1) {
match settings.load_file(path.into(), name.to_owned(), false) { setter(path.to_owned(), name.to_owned());
Err(e) => vec![e.msg.into()], vec![true.into()]
Ok(success) =>
super::utility::map_empty_result(
settings.clone().on_set(),
success
)
}
} else { } else {
vec!["load_settings missing name parameter".into()] vec!["load_settings missing name parameter".into()]
} }
@ -68,10 +68,17 @@ pub fn load_settings(
/// Generate load default settings from file web method /// Generate load default settings from file web method
pub fn load_default_settings( pub fn load_default_settings(
settings: Settings, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
.unwrap()
.send(ApiMessage::LoadMainSettings).expect("load_default_settings send failed");
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
match settings.load_file( setter();
vec![true.into()]
/*match settings.load_file(
crate::consts::DEFAULT_SETTINGS_FILE.into(), crate::consts::DEFAULT_SETTINGS_FILE.into(),
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
true true
@ -81,32 +88,76 @@ pub fn load_default_settings(
settings.clone().on_set(), settings.clone().on_set(),
success success
) )
}*/
} }
}
/// Generate load system default settings from file web method
pub fn load_system_settings(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
.unwrap()
.send(ApiMessage::LoadSystemSettings).expect("load_default_settings send failed");
move |_: super::ApiParameterType| {
setter();
vec![true.into()]
/*match settings.load_file(
crate::consts::DEFAULT_SETTINGS_FILE.into(),
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
true
) {
Err(e) => vec![e.msg.into()],
Ok(success) => super::utility::map_empty_result(
settings.clone().on_set(),
success
)
}*/
} }
} }
/// Generate get current settings name /// Generate get current settings name
pub fn get_name( pub fn get_name(
settings: Arc<Mutex<General>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl AsyncCallable {
move |_: super::ApiParameterType| { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let settings_lock = unwrap_lock(settings.lock(), "general"); let getter = move || {
vec![settings_lock let sender2 = sender.clone();
.name move || {
.clone() let (tx, rx) = mpsc::channel();
.into()] let callback = move |name: String| tx.send(name).expect("get_name callback send failed");
sender2.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetCurrentProfileName(Box::new(callback)))).expect("get_name send failed");
rx.recv().expect("get_name callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
vec![result.into()]
}
} }
} }
/// Generate wait for all locks to be available web method /// Generate wait for all locks to be available web method
pub fn lock_unlock_all( pub fn lock_unlock_all(
settings: Settings, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl AsyncCallable {
move |_: super::ApiParameterType| { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let _lock = unwrap_lock(settings.general.lock(), "general"); let getter = move || {
let _lock = unwrap_lock(settings.cpus.lock(), "cpus"); let sender2 = sender.clone();
let _lock = unwrap_lock(settings.gpu.lock(), "gpu"); move || {
let _lock = unwrap_lock(settings.battery.lock(), "battery"); let (tx, rx) = mpsc::channel();
let callback = move |x| tx.send(x).expect("lock_unlock_all callback send failed");
sender2.lock().unwrap().send(ApiMessage::WaitForEmptyQueue(Box::new(callback))).expect("lock_unlock_all send failed");
rx.recv().expect("lock_unlock_all callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |_| {
vec![true.into()] vec![true.into()]
} }
}
} }

View file

@ -1,31 +1,25 @@
use std::sync::{mpsc::Sender, Arc, Mutex}; use std::sync::mpsc::{Sender, self};
use std::sync::{Mutex, Arc};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
use crate::settings::{Gpu, OnSet, MinMax}; use crate::settings::MinMax;
use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use super::handler::{ApiMessage, GpuMessage};
pub fn set_ppt( pub fn set_ppt(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |fast: u64, slow: u64|
sender.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow)))).expect("set_ppt send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(fast_ppt)) = params_in.get(0) { if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) {
if let Some(Primitive::F64(slow_ppt)) = params_in.get(1) { if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) {
let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); setter(fast_ppt as u64, slow_ppt as u64);
settings_lock.fast_ppt = Some(*fast_ppt as u64); vec![(fast_ppt as u64).into(), (slow_ppt as u64).into()]
settings_lock.slow_ppt = Some(*slow_ppt as u64);
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
match settings_lock.on_set() {
Ok(_) => vec![
settings_lock.fast_ppt.unwrap().into(),
settings_lock.slow_ppt.unwrap().into()
],
Err(e) => vec![e.msg.into()],
}
} else { } else {
vec!["set_ppt missing parameter 1".into()] vec!["set_ppt missing parameter 1".into()]
} }
@ -36,60 +30,59 @@ pub fn set_ppt(
} }
pub fn get_ppt( pub fn get_ppt(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl AsyncCallable {
move |_: super::ApiParameterType| { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let settings_lock = unwrap_lock(settings.lock(), "gpu"); let getter = move || {
let fast_ppt = settings_lock.fast_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty); let sender2 = sender.clone();
let slow_ppt = settings_lock.slow_ppt.map(|x| x.into()).unwrap_or(Primitive::Empty); move || {
vec![fast_ppt, slow_ppt] let (tx, rx) = mpsc::channel();
let callback = move |ppt: (Option<u64>, Option<u64>)| tx.send(ppt).expect("get_ppt callback send failed");
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback)))).expect("get_ppt send failed");
rx.recv().expect("get_ppt callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |(fast, slow): (Option<u64>, Option<u64>)| {
vec![
fast.map(|x| x.into()).unwrap_or(Primitive::Empty),
slow.map(|x| x.into()).unwrap_or(Primitive::Empty),
]
}
} }
} }
pub fn unset_ppt( pub fn unset_ppt(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None))).expect("set_ppt send failed");
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); setter();
settings_lock.fast_ppt = None; vec![true.into()]
settings_lock.slow_ppt = None;
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(
settings_lock.on_set(),
Primitive::Empty,
)
} }
} }
pub fn set_clock_limits( pub fn set_clock_limits(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |value: MinMax<u64>|
sender.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value)))).expect("set_clock_limits send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(min)) = params_in.get(0) { if let Some(&Primitive::F64(min)) = params_in.get(0) {
if let Some(Primitive::F64(max)) = params_in.get(1) { if let Some(&Primitive::F64(max)) = params_in.get(1) {
let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); setter(MinMax {
settings_lock.clock_limits = Some(MinMax { min: min as _,
min: *min as _, max: max as _,
max: *max as _,
}); });
unwrap_maybe_fatal( vec![(min as u64).into(), (max as u64).into()]
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
match settings_lock.on_set() {
Ok(_) => vec![
settings_lock.clock_limits.as_ref().unwrap().min.into(),
settings_lock.clock_limits.as_ref().unwrap().max.into(),
],
Err(e) => vec![e.msg.into()]
}
} else { } else {
vec!["set_clock_limits missing parameter 1".into()] vec!["set_clock_limits missing parameter 1".into()]
} }
@ -100,51 +93,54 @@ pub fn set_clock_limits(
} }
pub fn get_clock_limits( pub fn get_clock_limits(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl AsyncCallable {
move |_: super::ApiParameterType| { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let settings_lock = unwrap_lock(settings.lock(), "gpu"); let getter = move|| {
if let Some(min_max) = &settings_lock.clock_limits { let sender2 = sender.clone();
vec![min_max.min.into(), min_max.max.into()] move || {
} else { let (tx, rx) = mpsc::channel();
vec![Primitive::Empty, Primitive::Empty] let callback = move |clocks: Option<MinMax<u64>>| tx.send(clocks).expect("get_clock_limits callback send failed");
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new(callback)))).expect("get_clock_limits send failed");
rx.recv().expect("get_clock_limits callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |clocks: Option<MinMax<u64>>| {
clocks.map(|x| vec![
x.min.into(), x.max.into()
]).unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty])
} }
} }
} }
pub fn unset_clock_limits( pub fn unset_clock_limits(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None))).expect("unset_clock_limits send failed");
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); setter();
settings_lock.clock_limits = None; vec![true.into()]
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(settings_lock.on_set(), true)
} }
} }
pub fn set_slow_memory( pub fn set_slow_memory(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
saver: Sender<()>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let saver = Mutex::new(saver); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |value: bool|
sender.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value))).expect("unset_clock_limits send failed");
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::Bool(memory_is_slow)) = params_in.get(0) { if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) {
let mut settings_lock = unwrap_lock(settings.lock(), "gpu"); setter(memory_is_slow);
settings_lock.slow_memory = *memory_is_slow; vec![memory_is_slow.into()]
unwrap_maybe_fatal(
unwrap_lock(saver.lock(), "save channel").send(()),
"Failed to send on save channel",
);
super::utility::map_empty_result(
settings_lock.on_set(),
settings_lock.slow_memory,
)
} else { } else {
vec!["set_slow_memory missing parameter 0".into()] vec!["set_slow_memory missing parameter 0".into()]
} }
@ -152,10 +148,22 @@ pub fn set_slow_memory(
} }
pub fn get_slow_memory( pub fn get_slow_memory(
settings: Arc<Mutex<Gpu>>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl AsyncCallable {
move |_: super::ApiParameterType| { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let settings_lock = unwrap_lock(settings.lock(), "cpu"); let getter = move || {
vec![settings_lock.slow_memory.into()] let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |value: bool| tx.send(value).expect("get_slow_memory callback send failed");
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(callback)))).expect("get_slow_memory send failed");
rx.recv().expect("get_slow_memory callback recv failed")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |value: bool| {
vec![value.into()]
}
} }
} }

199
backend/src/api/handler.rs Normal file
View file

@ -0,0 +1,199 @@
use std::sync::mpsc::{self, Receiver, Sender};
use crate::settings::{Settings, Cpu, Gpu, Battery, General, OnSet, OnResume, MinMax};
use crate::persist::SettingsJson;
use crate::utility::unwrap_maybe_fatal;
type Callback<T> = Box<dyn FnOnce(T) + Send>;
pub enum ApiMessage {
Battery(BatteryMessage),
Cpu(CpuMessage),
Gpu(GpuMessage),
General(GeneralMessage),
OnResume,
WaitForEmptyQueue(Callback<()>),
LoadSettings(String, String), // (path, name)
LoadMainSettings,
LoadSystemSettings,
}
pub enum BatteryMessage {
SetChargeRate(Option<u64>),
GetChargeRate(Callback<Option<u64>>),
}
impl BatteryMessage {
fn process(self, settings: &mut Battery) {
match self {
Self::SetChargeRate(rate) => settings.charge_rate = rate,
Self::GetChargeRate(cb) => cb(settings.charge_rate),
}
}
}
pub enum CpuMessage {
SetCpuOnline(usize, bool),
SetCpusOnline(Vec<bool>),
GetCpusOnline(Callback<Vec<bool>>),
SetClockLimits(usize, Option<MinMax<u64>>),
GetClockLimits(usize, Callback<Option<MinMax<u64>>>),
SetCpuGovernor(usize, String),
SetCpusGovernor(Vec<String>),
GetCpusGovernor(Callback<Vec<String>>),
}
impl CpuMessage {
fn process(self, settings: &mut Vec<Cpu>) {
match self {
Self::SetCpuOnline(index, status) => {settings.get_mut(index).map(|c| c.online = status);},
Self::SetCpusOnline(cpus) => {
for i in 0..cpus.len() {
settings.get_mut(i).map(|c| c.online = cpus[i]);
}
},
Self::GetCpusOnline(cb) => {
let mut result = Vec::with_capacity(settings.len());
for cpu in settings {
result.push(cpu.online);
}
cb(result);
},
Self::SetClockLimits(index, clocks) => {settings.get_mut(index).map(|c| c.clock_limits = clocks);},
Self::GetClockLimits(index, cb) => {settings.get(index).map(|c| cb(c.clock_limits.clone()));},
Self::SetCpuGovernor(index, gov) => {settings.get_mut(index).map(|c| c.governor = gov);},
Self::SetCpusGovernor(govs) => {
for i in 0..govs.len() {
settings.get_mut(i).map(|c| c.governor = govs[i].clone());
}
},
Self::GetCpusGovernor(cb) => {
let mut result = Vec::with_capacity(settings.len());
for cpu in settings {
result.push(cpu.governor.clone());
}
cb(result);
}
}
}
}
pub enum GpuMessage {
SetPpt(Option<u64>, Option<u64>), // (fast, slow)
GetPpt(Callback<(Option<u64>, Option<u64>)>),
SetClockLimits(Option<MinMax<u64>>),
GetClockLimits(Callback<Option<MinMax<u64>>>),
SetSlowMemory(bool),
GetSlowMemory(Callback<bool>),
}
impl GpuMessage {
fn process(self, settings: &mut Gpu) {
match self {
Self::SetPpt(fast, slow) => {
settings.fast_ppt = fast;
settings.slow_ppt = slow;
},
Self::GetPpt(cb) => cb((settings.fast_ppt, settings.slow_ppt)),
Self::SetClockLimits(clocks) => settings.clock_limits = clocks,
Self::GetClockLimits(cb) => cb(settings.clock_limits.clone()),
Self::SetSlowMemory(val) => settings.slow_memory = val,
Self::GetSlowMemory(cb) => cb(settings.slow_memory),
}
}
}
pub enum GeneralMessage {
SetPersistent(bool),
GetPersistent(Callback<bool>),
GetCurrentProfileName(Callback<String>),
}
impl GeneralMessage {
fn process(self, settings: &mut General) {
match self {
Self::SetPersistent(val) => settings.persistent = val,
Self::GetPersistent(cb) => cb(settings.persistent),
Self::GetCurrentProfileName(cb) => cb(settings.name.clone()),
}
}
}
pub struct ApiMessageHandler {
intake: Receiver<ApiMessage>,
on_empty: Vec<Callback<()>>,
}
impl ApiMessageHandler {
pub fn process_forever(&mut self, settings: &mut Settings) {
while let Ok(msg) = self.intake.recv() {
self.process(settings, msg);
while let Ok(msg) = self.intake.try_recv() {
self.process(settings, msg);
}
// run on_set
if let Err(e) = settings.on_set() {
log::error!("Settings on_set() err: {}", e);
}
// do callbacks
for func in self.on_empty.drain(..) {
func(());
}
// save
log::debug!("api_worker is saving...");
let is_persistent = settings.general.persistent;
if is_persistent {
let save_path = crate::utility::settings_dir()
.join(settings.general.path.clone());
let settings_clone = settings.clone();
let save_json: SettingsJson = settings_clone.into();
unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
log::debug!("Saved settings to {}", save_path.display());
} else {
log::debug!("Ignored save request for non-persistent settings");
}
}
}
pub fn process(&mut self, settings: &mut Settings, message: ApiMessage) {
match message {
ApiMessage::Battery(x) => x.process(&mut settings.battery),
ApiMessage::Cpu(x) => x.process(&mut settings.cpus),
ApiMessage::Gpu(x) => x.process(&mut settings.gpu),
ApiMessage::General(x) => x.process(&mut settings.general),
ApiMessage::OnResume => {
if let Err(e) = settings.on_resume() {
log::error!("Settings on_resume() err: {}", e);
}
}
ApiMessage::WaitForEmptyQueue(callback) => self.on_empty.push(callback),
ApiMessage::LoadSettings(path, name) => {
match settings.load_file(path.into(), name, false) {
Ok(success) => log::info!("Loaded settings file? {}", success),
Err(e) => log::warn!("Load file err: {}", e),
}
}
ApiMessage::LoadMainSettings => {
match settings.load_file(
crate::consts::DEFAULT_SETTINGS_FILE.into(),
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
true
) {
Ok(success) => log::info!("Loaded main settings file? {}", success),
Err(e) => log::warn!("Load file err: {}", e),
}
}
ApiMessage::LoadSystemSettings => {
settings.load_system_default();
}
}
}
pub fn new() -> (Self, Sender<ApiMessage>) {
let (tx, rx) = mpsc::channel();
(Self {
intake: rx,
on_empty: Vec::with_capacity(4),
}, tx)
}
}

View file

@ -2,6 +2,8 @@ pub mod battery;
pub mod cpu; pub mod cpu;
pub mod general; pub mod general;
pub mod gpu; pub mod gpu;
pub mod handler;
mod async_utils;
mod utility; mod utility;
pub(super) type ApiParameterType = Vec<usdpl_back::core::serdes::Primitive>; pub(super) type ApiParameterType = Vec<usdpl_back::core::serdes::Primitive>;

View file

@ -14,7 +14,7 @@ pub fn map_result<T: Into<Primitive>>(result: Result<T, SettingError>) -> super:
} }
} }
#[inline] /*#[inline]
pub fn map_empty_result<T: Into<Primitive>>( pub fn map_empty_result<T: Into<Primitive>>(
result: Result<(), SettingError>, result: Result<(), SettingError>,
success: T, success: T,
@ -26,4 +26,4 @@ pub fn map_empty_result<T: Into<Primitive>>(
vec![e.msg.into()] vec![e.msg.into()]
}, },
} }
} }*/

13
backend/src/api_worker.rs Normal file
View file

@ -0,0 +1,13 @@
use std::thread::{self, JoinHandle};
use crate::settings::Settings;
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use crate::api::handler::ApiMessageHandler;
pub fn spawn(mut settings: Settings, mut handler: ApiMessageHandler) -> JoinHandle<()> {
thread::spawn(move || {
log::info!("api_worker starting...");
handler.process_forever(&mut settings);
log::warn!("api_worker completed!");
})
}

View file

@ -4,4 +4,4 @@ pub const PACKAGE_NAME: &'static str = env!("CARGO_PKG_NAME");
pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION"); pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json"; pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json";
pub const DEFAULT_SETTINGS_NAME: &str = "Default"; pub const DEFAULT_SETTINGS_NAME: &str = "Main";

View file

@ -6,7 +6,8 @@ mod state;
mod consts; mod consts;
use consts::*; use consts::*;
mod resume_worker; mod resume_worker;
mod save_worker; //mod save_worker;
mod api_worker;
mod utility; mod utility;
use settings::OnSet; use settings::OnSet;
@ -49,14 +50,16 @@ fn main() -> Result<(), ()> {
log::debug!("Settings: {:?}", loaded_settings); log::debug!("Settings: {:?}", loaded_settings);
let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone()); let (api_handler, api_sender) = crate::api::handler::ApiMessageHandler::new();
let _resume_handle = resume_worker::spawn(loaded_settings.clone());
//let (_save_handle, save_sender) = save_worker::spawn(loaded_settings.clone());
let _resume_handle = resume_worker::spawn(api_sender.clone());
if let Err(e) = loaded_settings.on_set() { if let Err(e) = loaded_settings.on_set() {
log::error!("Startup Settings.on_set() error: {}", e); log::error!("Startup Settings.on_set() error: {}", e);
} }
Instance::new(PORT) let instance = Instance::new(PORT)
.register("V_INFO", |_: Vec<Primitive>| { .register("V_INFO", |_: Vec<Primitive>| {
vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()] vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()]
}) })
@ -67,107 +70,119 @@ fn main() -> Result<(), ()> {
.register("BATTERY_charge_design", api::battery::charge_design) .register("BATTERY_charge_design", api::battery::charge_design)
.register( .register(
"BATTERY_set_charge_rate", "BATTERY_set_charge_rate",
api::battery::set_charge_rate(loaded_settings.battery.clone(), save_sender.clone()), api::battery::set_charge_rate(api_sender.clone()),
) )
.register( .register(
"BATTERY_get_charge_rate", "BATTERY_get_charge_rate",
api::battery::get_charge_rate(loaded_settings.battery.clone()), api::battery::get_charge_rate(api_sender.clone()),
) )
.register( .register(
"BATTERY_unset_charge_rate", "BATTERY_unset_charge_rate",
api::battery::unset_charge_rate(loaded_settings.battery.clone(), save_sender.clone()), api::battery::unset_charge_rate(api_sender.clone()),
) )
// cpu API functions // cpu API functions
.register("CPU_count", api::cpu::max_cpus) .register("CPU_count", api::cpu::max_cpus)
.register( .register(
"CPU_set_online", "CPU_set_online",
api::cpu::set_cpu_online(loaded_settings.cpus.clone(), save_sender.clone()) api::cpu::set_cpu_online(api_sender.clone())
) )
.register( .register(
"CPU_set_onlines", "CPU_set_onlines",
api::cpu::set_cpus_online(loaded_settings.cpus.clone(), save_sender.clone()) api::cpu::set_cpus_online(api_sender.clone())
) )
.register( .register_async(
"CPU_get_onlines", "CPU_get_onlines",
api::cpu::get_cpus_online(loaded_settings.cpus.clone()) api::cpu::get_cpus_online(api_sender.clone())
) )
.register( .register(
"CPU_set_clock_limits", "CPU_set_clock_limits",
api::cpu::set_clock_limits(loaded_settings.cpus.clone(), save_sender.clone()) api::cpu::set_clock_limits(api_sender.clone())
) )
.register( .register(
"CPU_get_clock_limits", "CPU_get_clock_limits",
api::cpu::get_clock_limits(loaded_settings.cpus.clone()) api::cpu::get_clock_limits(api_sender.clone())
) )
.register( .register(
"CPU_unset_clock_limits", "CPU_unset_clock_limits",
api::cpu::unset_clock_limits(loaded_settings.cpus.clone(), save_sender.clone()) api::cpu::unset_clock_limits(api_sender.clone())
) )
.register( .register(
"CPU_set_governor", "CPU_set_governor",
api::cpu::set_cpu_governor(loaded_settings.cpus.clone(), save_sender.clone()) api::cpu::set_cpu_governor(api_sender.clone())
)
.register(
"CPU_set_governors",
api::cpu::set_cpus_governors(api_sender.clone())
) )
.register( .register(
"CPU_get_governors", "CPU_get_governors",
api::cpu::get_cpu_governors(loaded_settings.cpus.clone()) api::cpu::get_cpu_governors(api_sender.clone())
) )
// gpu API functions // gpu API functions
.register( .register(
"GPU_set_ppt", "GPU_set_ppt",
api::gpu::set_ppt(loaded_settings.gpu.clone(), save_sender.clone()) api::gpu::set_ppt(api_sender.clone())
) )
.register( .register_async(
"GPU_get_ppt", "GPU_get_ppt",
api::gpu::get_ppt(loaded_settings.gpu.clone()) api::gpu::get_ppt(api_sender.clone())
) )
.register( .register(
"GPU_unset_ppt", "GPU_unset_ppt",
api::gpu::unset_ppt(loaded_settings.gpu.clone(), save_sender.clone()) api::gpu::unset_ppt(api_sender.clone())
) )
.register( .register(
"GPU_set_clock_limits", "GPU_set_clock_limits",
api::gpu::set_clock_limits(loaded_settings.gpu.clone(), save_sender.clone()) api::gpu::set_clock_limits(api_sender.clone())
) )
.register( .register_async(
"GPU_get_clock_limits", "GPU_get_clock_limits",
api::gpu::get_clock_limits(loaded_settings.gpu.clone()) api::gpu::get_clock_limits(api_sender.clone())
) )
.register( .register(
"GPU_unset_clock_limits", "GPU_unset_clock_limits",
api::gpu::unset_clock_limits(loaded_settings.gpu.clone(), save_sender.clone()) api::gpu::unset_clock_limits(api_sender.clone())
) )
.register( .register(
"GPU_set_slow_memory", "GPU_set_slow_memory",
api::gpu::set_slow_memory(loaded_settings.gpu.clone(), save_sender.clone()) api::gpu::set_slow_memory(api_sender.clone())
) )
.register( .register_async(
"GPU_get_slow_memory", "GPU_get_slow_memory",
api::gpu::get_slow_memory(loaded_settings.gpu.clone()) api::gpu::get_slow_memory(api_sender.clone())
) )
// general API functions // general API functions
.register( .register(
"GENERAL_set_persistent", "GENERAL_set_persistent",
api::general::set_persistent(loaded_settings.general.clone(), save_sender.clone()) api::general::set_persistent(api_sender.clone())
) )
.register( .register(
"GENERAL_get_persistent", "GENERAL_get_persistent",
api::general::get_persistent(loaded_settings.general.clone()) api::general::get_persistent(api_sender.clone())
) )
.register( .register(
"GENERAL_load_settings", "GENERAL_load_settings",
api::general::load_settings(loaded_settings.clone()) api::general::load_settings(api_sender.clone())
) )
.register( .register(
"GENERAL_load_default_settings", "GENERAL_load_default_settings",
api::general::load_default_settings(loaded_settings.clone()) api::general::load_default_settings(api_sender.clone())
) )
.register( .register(
"GENERAL_load_system_settings",
api::general::load_system_settings(api_sender.clone())
)
.register_async(
"GENERAL_get_name", "GENERAL_get_name",
api::general::get_name(loaded_settings.general.clone()) api::general::get_name(api_sender.clone())
) )
.register( .register_async(
"GENERAL_wait_for_unlocks", "GENERAL_wait_for_unlocks",
api::general::lock_unlock_all(loaded_settings.clone()) api::general::lock_unlock_all(api_sender.clone())
) );
api_worker::spawn(loaded_settings, api_handler);
instance
.run_blocking() .run_blocking()
} }

View file

@ -1,12 +1,13 @@
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::sync::mpsc::Sender;
use crate::settings::{OnResume, Settings}; use crate::api::handler::ApiMessage;
use crate::utility::unwrap_maybe_fatal; //use crate::utility::unwrap_maybe_fatal;
const ALLOWED_ERROR: f64 = 100.0; // period of 10ms with 100x means sleep has to be >= 1s to be detected const ALLOWED_ERROR: f64 = 100.0; // period of 10ms with 100x means sleep has to be >= 1s to be detected
pub fn spawn(settings: Settings) -> JoinHandle<()> { pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
thread::spawn(move || { thread::spawn(move || {
log::info!("resume_worker starting..."); log::info!("resume_worker starting...");
let duration = Duration::from_millis(10); // very low so it detects before Steam client does let duration = Duration::from_millis(10); // very low so it detects before Steam client does
@ -18,7 +19,7 @@ pub fn spawn(settings: Settings) -> JoinHandle<()> {
if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) { if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) {
// has just resumed from sleep // has just resumed from sleep
log::info!("Resume detected"); log::info!("Resume detected");
unwrap_maybe_fatal(settings.on_resume(), "On resume failure"); sender.send(ApiMessage::OnResume).expect("resume_worker send failed");
log::debug!( log::debug!(
"OnResume completed after sleeping for {}s", "OnResume completed after sleeping for {}s",
old_start.as_secs_f32() old_start.as_secs_f32()

View file

@ -1,11 +1,11 @@
use std::convert::Into; use std::convert::Into;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, Mutex}; //use std::sync::{Arc, Mutex};
use super::{Battery, Cpu, Gpu}; use super::{Battery, Cpu, Gpu};
use super::{OnResume, OnSet, SettingError}; use super::{OnResume, OnSet, SettingError};
use crate::persist::{CpuJson, SettingsJson}; use crate::persist::{CpuJson, SettingsJson};
use crate::utility::unwrap_lock; //use crate::utility::unwrap_lock;
const LATEST_VERSION: u64 = 0; const LATEST_VERSION: u64 = 0;
@ -43,24 +43,20 @@ impl OnSet for General {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Settings { pub struct Settings {
pub general: Arc<Mutex<General>>, pub general: General,
pub cpus: Arc<Mutex<Vec<Cpu>>>, pub cpus: Vec<Cpu>,
pub gpu: Arc<Mutex<Gpu>>, pub gpu: Gpu,
pub battery: Arc<Mutex<Battery>>, pub battery: Battery,
} }
impl OnSet for Settings { impl OnSet for Settings {
fn on_set(&mut self) -> Result<(), SettingError> { fn on_set(&mut self) -> Result<(), SettingError> {
unwrap_lock(self.battery.lock(), "battery").on_set()?; self.battery.on_set()?;
{ for cpu in self.cpus.iter_mut() {
// cpu lock scope
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
for cpu in cpu_lock.iter_mut() {
cpu.on_set()?; cpu.on_set()?;
} }
} self.gpu.on_set()?;
unwrap_lock(self.gpu.lock(), "gpu").on_set()?; self.general.on_set()?;
unwrap_lock(self.general.lock(), "general").on_set()?;
Ok(()) Ok(())
} }
} }
@ -70,24 +66,24 @@ impl Settings {
pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self { pub fn from_json(other: SettingsJson, json_path: PathBuf) -> Self {
match other.version { match other.version {
0 => Self { 0 => Self {
general: Arc::new(Mutex::new(General { general: General {
persistent: other.persistent, persistent: other.persistent,
path: json_path, path: json_path,
name: other.name, name: other.name,
})), },
cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))), cpus: Self::convert_cpus(other.cpus, other.version),
gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))), gpu: Gpu::from_json(other.gpu, other.version),
battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))), battery: Battery::from_json(other.battery, other.version),
}, },
_ => Self { _ => Self {
general: Arc::new(Mutex::new(General { general: General {
persistent: other.persistent, persistent: other.persistent,
path: json_path, path: json_path,
name: other.name, name: other.name,
})), },
cpus: Arc::new(Mutex::new(Self::convert_cpus(other.cpus, other.version))), cpus: Self::convert_cpus(other.cpus, other.version),
gpu: Arc::new(Mutex::new(Gpu::from_json(other.gpu, other.version))), gpu: Gpu::from_json(other.gpu, other.version),
battery: Arc::new(Mutex::new(Battery::from_json(other.battery, other.version))), battery: Battery::from_json(other.battery, other.version),
}, },
} }
} }
@ -117,35 +113,26 @@ impl Settings {
pub fn system_default(json_path: PathBuf) -> Self { pub fn system_default(json_path: PathBuf) -> Self {
Self { Self {
general: Arc::new(Mutex::new(General { general: General {
persistent: false, persistent: false,
path: json_path, path: json_path,
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
})), },
cpus: Arc::new(Mutex::new(Cpu::system_default())), cpus: Cpu::system_default(),
gpu: Arc::new(Mutex::new(Gpu::system_default())), gpu: Gpu::system_default(),
battery: Arc::new(Mutex::new(Battery::system_default())), battery: Battery::system_default(),
} }
} }
fn load_system_default(&self) { pub fn load_system_default(&mut self) {
{ self.cpus = Cpu::system_default();
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); self.gpu = Gpu::system_default();
*cpu_lock = Cpu::system_default(); self.battery = Battery::system_default();
}
{
let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
*gpu_lock = Gpu::system_default();
}
{
let mut battery_lock = unwrap_lock(self.battery.lock(), "battery");
*battery_lock = Battery::system_default();
}
} }
pub fn load_file(&self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> { pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> {
let json_path = crate::utility::settings_dir().join(filename); let json_path = crate::utility::settings_dir().join(filename);
let mut general_lock = unwrap_lock(self.general.lock(), "general"); //let mut general_lock = unwrap_lock(self.general.lock(), "general");
if json_path.exists() { if json_path.exists() {
let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError { let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError {
msg: e.to_string(), msg: e.to_string(),
@ -153,53 +140,38 @@ impl Settings {
})?; })?;
if !settings_json.persistent { if !settings_json.persistent {
log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display()); log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display());
general_lock.persistent = false; self.general.persistent = false;
general_lock.name = name; self.general.name = name;
} else { } else {
let new_cpus = Self::convert_cpus(settings_json.cpus, settings_json.version); self.cpus = Self::convert_cpus(settings_json.cpus, settings_json.version);
let new_gpu = Gpu::from_json(settings_json.gpu, settings_json.version); self.gpu = Gpu::from_json(settings_json.gpu, settings_json.version);
let new_battery = Battery::from_json(settings_json.battery, settings_json.version); self.battery = Battery::from_json(settings_json.battery, settings_json.version);
{ self.general.persistent = true;
let mut cpu_lock = unwrap_lock(self.cpus.lock(), "cpu"); self.general.name = settings_json.name;
*cpu_lock = new_cpus;
}
{
let mut gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
*gpu_lock = new_gpu;
}
{
let mut battery_lock = unwrap_lock(self.battery.lock(), "battery");
*battery_lock = new_battery;
}
general_lock.persistent = true;
general_lock.name = settings_json.name;
} }
} else { } else {
if system_defaults { if system_defaults {
self.load_system_default(); self.load_system_default();
} }
general_lock.persistent = false; self.general.persistent = false;
general_lock.name = name; self.general.name = name;
} }
general_lock.path = json_path; self.general.path = json_path;
Ok(general_lock.persistent) Ok(self.general.persistent)
} }
} }
impl OnResume for Settings { impl OnResume for Settings {
fn on_resume(&self) -> Result<(), SettingError> { fn on_resume(&self) -> Result<(), SettingError> {
log::debug!("Locking settings for on_resume"); log::debug!("Applying settings for on_resume");
unwrap_lock(self.battery.lock(), "battery").on_resume()?; self.battery.on_resume()?;
log::debug!("Got battery lock"); log::debug!("Resumed battery");
{ for cpu in self.cpus.iter() {
let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
log::debug!("Got cpus lock");
for cpu in cpu_lock.iter() {
cpu.on_resume()?; cpu.on_resume()?;
} }
} log::debug!("Resumed CPUs");
unwrap_lock(self.gpu.lock(), "gpu").on_resume()?; self.gpu.on_resume()?;
log::debug!("Got gpu lock"); log::debug!("Resumed GPU");
Ok(()) Ok(())
} }
} }
@ -207,26 +179,18 @@ impl OnResume for Settings {
impl Into<SettingsJson> for Settings { impl Into<SettingsJson> for Settings {
#[inline] #[inline]
fn into(self) -> SettingsJson { fn into(self) -> SettingsJson {
log::debug!("Locking settings to convert into json"); log::debug!("Converting into json");
let gen_lock = unwrap_lock(self.general.lock(), "general");
log::debug!("Got general lock");
let cpu_lock = unwrap_lock(self.cpus.lock(), "cpu");
log::debug!("Got cpus lock");
let gpu_lock = unwrap_lock(self.gpu.lock(), "gpu");
log::debug!("Got gpu lock");
let batt_lock = unwrap_lock(self.battery.lock(), "battery");
log::debug!("Got battery lock");
SettingsJson { SettingsJson {
version: LATEST_VERSION, version: LATEST_VERSION,
name: gen_lock.name.clone(), name: self.general.name.clone(),
persistent: gen_lock.persistent, persistent: self.general.persistent,
cpus: cpu_lock cpus: self.cpus
.clone() .clone()
.drain(..) .drain(..)
.map(|cpu| cpu.into()) .map(|cpu| cpu.into())
.collect(), .collect(),
gpu: gpu_lock.clone().into(), gpu: self.gpu.clone().into(),
battery: batt_lock.clone().into(), battery: self.battery.clone().into(),
} }
} }
} }

View file

@ -1,5 +1,5 @@
use std::fmt::Display; use std::fmt::Display;
use std::sync::{LockResult, MutexGuard}; //use std::sync::{LockResult, MutexGuard};
pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &str) -> T { pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &str) -> T {
match result { match result {
@ -11,7 +11,7 @@ pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &
} }
} }
pub fn unwrap_lock<'a, T: Sized>( /*pub fn unwrap_lock<'a, T: Sized>(
result: LockResult<MutexGuard<'a, T>>, result: LockResult<MutexGuard<'a, T>>,
lock_name: &str, lock_name: &str,
) -> MutexGuard<'a, T> { ) -> MutexGuard<'a, T> {
@ -22,7 +22,7 @@ pub fn unwrap_lock<'a, T: Sized>(
panic!("Failed to acquire {} lock: {}", lock_name, e); panic!("Failed to acquire {} lock: {}", lock_name, e);
} }
} }
} }*/
pub fn settings_dir() -> std::path::PathBuf { pub fn settings_dir() -> std::path::PathBuf {
usdpl_back::api::dirs::home() usdpl_back::api::dirs::home()

View file

@ -1,6 +1,6 @@
{ {
"name": "PowerTools", "name": "PowerTools",
"version": "1.0.5", "version": "1.1.0",
"description": "Power tweaks for power users", "description": "Power tweaks for power users",
"scripts": { "scripts": {
"build": "shx rm -rf dist && rollup -c", "build": "shx rm -rf dist && rollup -c",