replace top level mutex with rw lock

This commit is contained in:
🪞👃🪞 2024-07-05 20:02:55 +03:00
parent 33de8bbf1d
commit 2989c79fd0
5 changed files with 21 additions and 15 deletions

View file

@ -34,7 +34,7 @@ submod!( handle midi render time );
pub type Usually<T> = Result<T, Box<dyn Error>>; pub type Usually<T> = Result<T, Box<dyn Error>>;
/// A UI component. /// A UI component.
pub trait Component: Render + Handle { pub trait Component: Render + Handle + Sync {
/// Perform type erasure for collecting heterogeneous components. /// Perform type erasure for collecting heterogeneous components.
fn boxed (self) -> Box<dyn Component> where Self: Sized + 'static { fn boxed (self) -> Box<dyn Component> where Self: Sized + 'static {
Box::new(self) Box::new(self)
@ -42,7 +42,7 @@ pub trait Component: Render + Handle {
} }
/// Anything that implements `Render` + `Handle` can be used as a UI component. /// Anything that implements `Render` + `Handle` can be used as a UI component.
impl<T: Render + Handle> Component for T {} impl<T: Render + Handle + Sync> Component for T {}
/// A UI component that may be associated with a JACK client by the `Jack` factory. /// A UI component that may be associated with a JACK client by the `Jack` factory.
pub trait Device: Render + Handle + Process + Send + Sync { pub trait Device: Render + Handle + Process + Send + Sync {
@ -61,11 +61,11 @@ pub use crate::{submod, render, handle, process, phrase, keymap, key, ports};
// Reexport JACK proto-lib: // Reexport JACK proto-lib:
pub use crate::jack::*; pub use crate::jack::*;
impl<T: Render + Handle + Send + Sized + 'static> Run for T {} impl<T: Render + Handle + Send + Sync + Sized + 'static> Run for T {}
pub trait Run: Render + Handle + Send + Sized + 'static { pub trait Run: Render + Handle + Send + Sync + Sized + 'static {
fn run (self, init: Option<impl FnOnce(Arc<Mutex<Self>>)->Usually<()>>) -> Usually<()> { fn run (self, init: Option<impl FnOnce(Arc<RwLock<Self>>)->Usually<()>>) -> Usually<()> {
let app = Arc::new(Mutex::new(self)); let app = Arc::new(RwLock::new(self));
let exited = Arc::new(AtomicBool::new(false)); let exited = Arc::new(AtomicBool::new(false));
let _input_thread = input_thread(&exited, &app); let _input_thread = input_thread(&exited, &app);
terminal_setup()?; terminal_setup()?;
@ -106,7 +106,7 @@ pub fn terminal_teardown () -> Usually<()> {
/// Main thread render loop /// Main thread render loop
pub fn main_thread ( pub fn main_thread (
exited: &Arc<AtomicBool>, exited: &Arc<AtomicBool>,
device: &Arc<Mutex<impl Render + Send + 'static>> device: &Arc<RwLock<impl Render + Send + Sync + 'static>>
) -> Usually<JoinHandle<()>> { ) -> Usually<JoinHandle<()>> {
let exited = exited.clone(); let exited = exited.clone();
let device = device.clone(); let device = device.clone();
@ -117,7 +117,7 @@ pub fn main_thread (
terminal.draw(|frame|{ terminal.draw(|frame|{
let area = frame.size(); let area = frame.size();
let buffer = frame.buffer_mut(); let buffer = frame.buffer_mut();
device.lock().unwrap() device.read().unwrap()
.render(buffer, area) .render(buffer, area)
.expect("Failed to render content"); .expect("Failed to render content");
}).expect("Failed to render frame"); }).expect("Failed to render frame");
@ -134,7 +134,7 @@ pub fn main_thread (
/// Spawn thread that listens for user input /// Spawn thread that listens for user input
pub fn input_thread ( pub fn input_thread (
exited: &Arc<AtomicBool>, exited: &Arc<AtomicBool>,
device: &Arc<Mutex<impl Handle + Send + 'static>> device: &Arc<RwLock<impl Handle + Send + Sync + 'static>>
) -> JoinHandle<()> { ) -> JoinHandle<()> {
let poll = Duration::from_millis(100); let poll = Duration::from_millis(100);
let exited = exited.clone(); let exited = exited.clone();
@ -155,7 +155,7 @@ pub fn input_thread (
}) => { }) => {
exited.store(true, Ordering::Relaxed); exited.store(true, Ordering::Relaxed);
}, },
_ => if device.lock().unwrap().handle(&AppEvent::Input(event)).is_err() { _ => if device.write().unwrap().handle(&AppEvent::Input(event)).is_err() {
break break
} }
} }

View file

@ -62,6 +62,12 @@ impl<T: Render> Render for Arc<Mutex<T>> {
} }
} }
impl<T: Render + Sync> Render for Arc<RwLock<T>> {
fn render (&self, b: &mut Buffer, a: Rect) -> Usually<Rect> {
self.read().unwrap().render(b, a)
}
}
impl WidgetRef for &dyn Render { impl WidgetRef for &dyn Render {
fn render_ref (&self, area: Rect, buf: &mut Buffer) { fn render_ref (&self, area: Rect, buf: &mut Buffer) {
Render::render(*self, buf, area).expect("Failed to render device."); Render::render(*self, buf, area).expect("Failed to render device.");

View file

@ -43,7 +43,7 @@ pub use ::_jack::{
}; };
/// Just run thing with JACK. Returns the activated client. /// Just run thing with JACK. Returns the activated client.
pub fn jack_run <T> (name: &str, app: &Arc<Mutex<T>>) -> Usually<DynamicAsyncClient> pub fn jack_run <T: Sync> (name: &str, app: &Arc<RwLock<T>>) -> Usually<DynamicAsyncClient>
where T: Handle + Process + Send + 'static where T: Handle + Process + Send + 'static
{ {
let options = ClientOptions::NO_START_SERVER; let options = ClientOptions::NO_START_SERVER;
@ -59,7 +59,7 @@ pub fn jack_run <T> (name: &str, app: &Arc<Mutex<T>>) -> Usually<DynamicAsyncCli
ClosureProcessHandler::new(Box::new({ ClosureProcessHandler::new(Box::new({
let app = app.clone(); let app = app.clone();
move|c: &Client, s: &ProcessScope|{ move|c: &Client, s: &ProcessScope|{
app.lock().unwrap().process(c, s) app.write().unwrap().process(c, s)
//Control::Continue //Control::Continue
} }
}) as BoxedProcessHandler) }) as BoxedProcessHandler)

View file

@ -37,8 +37,8 @@ pub fn main () -> Usually<()> {
app.quant = 24; app.quant = 24;
// Start main loop // Start main loop
app.run(Some(|app: Arc<Mutex<App>>|{ app.run(Some(|app: Arc<RwLock<App>>|{
let mut state = app.lock().unwrap(); let mut state = app.write().unwrap();
// Start JACK and setup device graph // Start JACK and setup device graph
let jack = jack_run("tek", &app)?; let jack = jack_run("tek", &app)?;

View file

@ -63,7 +63,7 @@ impl Phrase {
_ => {} _ => {}
} }
LiveEvent::Midi { channel, message }.write(&mut buf).unwrap(); LiveEvent::Midi { channel, message }.write(&mut buf).unwrap();
let t = *time as usize; let t = *time as usize; // FIXME miscalculated, skipping notes
output[t].push(buf); output[t].push(buf);
} }
} }