diff --git a/Cargo.lock b/Cargo.lock index c0116f9..1acd8b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -797,21 +797,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b854b0e584ead1a33f18b2fcad7cf7be18b3875c78816b753639aa501513ae" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows-link", - "windows-result", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1193,19 +1178,6 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lru" version = "0.18.2" @@ -1225,15 +1197,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - [[package]] name = "memchr" version = "2.8.3" @@ -2652,7 +2615,6 @@ dependencies = [ "konst", "midly", "palette", - "parking_lot", "profiling", "proptest", "proptest-derive", @@ -2663,7 +2625,6 @@ dependencies = [ "tracing", "tracing-flame", "tracing-subscriber", - "tracing-tracy", "unicode-width", "winit", ] @@ -2929,50 +2890,14 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ - "matchers", "nu-ansi-term", - "once_cell", - "regex-automata", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", ] -[[package]] -name = "tracing-tracy" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" -dependencies = [ - "tracing-core", - "tracing-subscriber", - "tracy-client", -] - -[[package]] -name = "tracy-client" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f6fc3baeac5d86ab90c772e9e30620fc653bf1864295029921a15ef478e6a5" -dependencies = [ - "loom", - "once_cell", - "tracy-client-sys", -] - -[[package]] -name = "tracy-client-sys" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f7c95348f20c1c913d72157b3c6dee6ea3e30b3d19502c5a7f6d3f160dacbf" -dependencies = [ - "cc", - "windows-targets", -] - [[package]] name = "ttf-parser" version = "0.25.1" @@ -3407,15 +3332,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 984508f..fea5807 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,6 @@ anyhow = { version = "1.0" } atomic_float = { version = "1" } better-panic = { version = "0.3.0" } konst = { version = "0.3.16", features = [ "rust_1_83" ] } -parking_lot = { version = "0.12.5" } bumpalo = { optional = true, version = "3.19.0" } crossterm = { optional = true, version = "0.29.0" } @@ -45,8 +44,6 @@ profiling = { version = "1.0.18", optional = true, features = ["profile tracing = { version = "0.1", optional = true, default-features = false, features = [ "std" ] } tracing-subscriber = { version = "0.3", optional = true } tracing-flame = { version = "0.2", optional = true } -tracing-tracy = { version = "0.11.4", optional = true } - [dev-dependencies] proptest = { version = "^1" } diff --git a/src/deps.rs b/src/deps.rs deleted file mode 100644 index 5b3dd7f..0000000 --- a/src/deps.rs +++ /dev/null @@ -1,29 +0,0 @@ -pub extern crate atomic_float; -pub extern crate palette; -pub extern crate better_panic; -pub extern crate unicode_width; -pub extern crate parking_lot; -pub(crate) use ::{ - std::fmt::{Debug, Display}, - std::ops::{Add, Sub, Mul, Div}, - std::sync::Arc, - std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::*}, - std::marker::PhantomData -}; - -pub(crate) use ::parking_lot::RwLock; - -#[cfg(feature = "lang")] pub use ::dizzle::*; -#[cfg(feature = "prof")] pub extern crate profiling; -#[cfg(feature = "prof")] pub extern crate tracing; -#[cfg(feature = "prof")] pub extern crate tracing_subscriber; -#[cfg(feature = "prof")] pub extern crate tracing_flame; -//#[cfg(feature = "prof")] pub extern crate tracing_tracy; -#[cfg(feature = "sing")] pub extern crate jack; -#[cfg(feature = "midi")] pub extern crate midly; -#[cfg(feature = "term")] pub extern crate ratatui; -#[cfg(feature = "term")] pub extern crate crossterm; -#[cfg(feature = "lang")] pub extern crate dizzle; - -#[cfg(test)] #[macro_use] pub extern crate proptest; -#[cfg(test)] pub(crate) use proptest_derive::Arbitrary; diff --git a/src/layout/area.rs b/src/layout/area.rs index 89d9e4d..11647eb 100644 --- a/src/layout/area.rs +++ b/src/layout/area.rs @@ -19,7 +19,6 @@ pub struct Area( impl<'a, S: Screen, T: Draw> Draw for Area { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("area_draw"); to.draw(self.0, &self.1) } } diff --git a/src/layout/axis.rs b/src/layout/axis.rs index 0ea9cfa..37c98df 100644 --- a/src/layout/axis.rs +++ b/src/layout/axis.rs @@ -297,7 +297,6 @@ where impl <'a, S: Screen, I: Draw> Draw for Full<'a, S, I> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("full_draw"); let XYWH(x0, y0, w0, h0) = to.area(); let item = match self { Self::W(i) => i, Self::H(i) => i, Self::WH(i) => i, _ => unreachable!() @@ -316,7 +315,6 @@ impl <'a, S: Screen, I: Draw> Draw for Full<'a, S, I> { impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Exact<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("exact_draw"); let XYWH(x0, y0, w0, h0) = to.area(); let (item, w1, h1) = match self { Self::W(item, w1) => (item, (*w1).into(), None), @@ -339,7 +337,6 @@ impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Ex impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Min<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("min_draw"); let XYWH(x0, y0, w0, h0) = to.area(); let (item, w1, h1) = match self { Self::W(item, w1) => (item, (*w1).into(), None), @@ -361,7 +358,6 @@ impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Mi impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Max<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("max_draw"); let XYWH(x, y, w0, h0) = to.area(); let (item, w, h) = match self { Self::W(item, w) => (item, (*w).into().unwrap_or(w0), h0), @@ -375,7 +371,6 @@ impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Ma impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Push<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("push_draw"); match self { Self::__(_) => unreachable!(), Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => { @@ -394,7 +389,6 @@ impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Pu impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Pull<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("pull_draw"); match self { Self::__(_) => unreachable!(), Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => { @@ -419,7 +413,6 @@ impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Pu impl <'a, S: Screen, I: Draw, X: Into> + Copy> Draw for Pad<'a, S, I, X> { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("pad_draw"); let XYWH(x, y, w0, h0) = to.area(); let (item, w, h) = match self { Self::X(item, w) => (item, (*w).into().unwrap_or_default(), Default::default()), diff --git a/src/layout/azimuth.rs b/src/layout/azimuth.rs index 53c8853..9433ed3 100644 --- a/src/layout/azimuth.rs +++ b/src/layout/azimuth.rs @@ -116,17 +116,16 @@ pub trait CanAlign<'a, S: Screen>: Draw + Sized { } pub struct Align( - pub Option, - pub T, + pub(crate) Option, + pub(crate) T, ); impl<'a, S: Screen, T: Draw> Draw for Align { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("align_draw"); let Self(azimuth, item) = self; let area0 = to.area(); let size = to.size(area0, item)?; - let area1 = aligned::(area0, size, *azimuth); + let area1 = align::(area0, size, *azimuth); //println!("\n\r{azimuth:?} {area0:?} {size:?}=>{area1:?}"); Ok(if let Some(area) = area1 { to.draw(area, &item)? @@ -136,10 +135,9 @@ impl<'a, S: Screen, T: Draw> Draw for Align { } } -fn aligned ( +fn align ( area0: XYWH, area: Option>, azimuth: Option ) -> Option> { - #[cfg(feature = "prof")] profiling::scope!("align"); area.map(|XYWH(x, y, w, h)|{ let XYWH(x0, y0, w0, h0) = area0; match azimuth { @@ -160,7 +158,6 @@ fn aligned ( } fn_kw_layout!(kw_split |state, output, expr| { - #[cfg(feature = "prof")] profiling::scope!("kw_split"); let thunk_a = draw(move|screen|ok_flat(expr.nth(1)?.map(|x|state.interpret(screen, x)))); let thunk_b = draw(move|screen|ok_flat(expr.nth(2)?.map(|x|state.interpret(screen, x)))); Ok(match expr.head()? { @@ -208,7 +205,6 @@ pub fn split <'a, S: Screen, A: Draw, B: Draw> ( impl<'a, S: Screen, A: Draw, B: Draw> Draw for Pair { fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("pair_draw"); let Self(split, a, b, ..) = self; let (area_a, area_b) = stack_areas(split, to, a, b)?; let (drawn_a, drawn_b) = draw_stacks(split, to, a, area_a, None, b, area_b, None)?; @@ -226,7 +222,6 @@ fn draw_stacks <'a, S: Screen> ( area_b: impl Into>>, origin_b: impl Into>, ) -> UsuallyRef<'a, (Option>, Option>)> { - #[cfg(feature = "prof")] profiling::scope!("draw_stacks"); let draw_a = |to: &mut S|Ok::<_, Box>(match origin_a.into() { Some(origin_a) => to.draw(area_a.into(), a.align(origin_a))?, None => to.draw(area_a.into(), a)? @@ -308,7 +303,6 @@ fn stack_drawn ( drawn_a: Option>, drawn_b: Option>, ) -> Option> { - #[cfg(feature = "prof")] profiling::scope!("stack_drawn"); if let (Some(XYWH(xa, ya, wa, ha)), Some(XYWH(xb, yb, wb, hb))) = (drawn_a, drawn_b) { match split { Split::South => Some(XYWH(xa.min(xb), ya, wa.max(wb), ha + hb)), diff --git a/src/layout/cond.rs b/src/layout/cond.rs index 496f575..9dab1d1 100644 --- a/src/layout/cond.rs +++ b/src/layout/cond.rs @@ -1,28 +1,11 @@ use crate::*; -pub struct When(pub bool, pub T); - -impl> Draw for When { - fn draw (&self, to: &mut S) -> Drawn { - #[cfg(feature = "prof")] profiling::scope!("when"); - if self.0 { - self.1.draw(to) - } else { - Ok(Default::default()) - } - } -} - -impl When { - - fn_kw_layout!(interpret |state, output, expr| { - #[cfg(feature = "prof")] profiling::scope!("kw_when"); - let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x|state.interpret(screen, x)))); - ok_flat(matches!(expr.head()?, Some("when")).then(||{ - when(state.namespace(&expr.nth(1)?)?.unwrap(), thunk).draw(output) - })) - }); -} +fn_kw_layout!(kw_when |state, output, expr| { + let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x|state.interpret(screen, x)))); + ok_flat(matches!(expr.head()?, Some("when")).then(||{ + when(state.namespace(&expr.nth(1)?)?.unwrap(), thunk).draw(output) + })) +}); /// Only render when condition is true. /// @@ -32,11 +15,10 @@ impl When { /// # } /// ``` pub const fn when <'a, T: Screen> (condition: bool, item: impl Draw) -> impl Draw { - When(condition, item) + draw(move|to: &mut T|if condition { item.draw(to) } else { Ok(Default::default()) }) } fn_kw_layout!(kw_either |state, output, expr| { - #[cfg(feature = "prof")] profiling::scope!("kw_layout"); let thunk_a = draw(move|screen|ok_flat(expr.nth(2)?.map(|x|state.interpret(screen, x)))); let thunk_b = draw(move|screen|ok_flat(expr.nth(3)?.map(|x|state.interpret(screen, x)))); ok_flat(matches!(expr.head()?, Some("either")).then(||{ @@ -54,8 +36,5 @@ fn_kw_layout!(kw_either |state, output, expr| { pub const fn either <'a, T: Screen> ( condition: bool, a: impl Draw, b: impl Draw ) -> impl Draw { - draw(move|to: &mut T|{ - #[cfg(feature = "prof")] profiling::scope!("either"); - if condition { a.draw(to) } else { b.draw(to) } - }) + draw(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) }) } diff --git a/src/lib.rs b/src/lib.rs index d68e831..aad88f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,28 @@ //#![feature(trait_alias)] //#![feature(type_alias_impl_trait)] //#![feature(type_changing_struct_update)] -mod deps; pub use self::deps::*; +pub extern crate atomic_float; +pub extern crate palette; +pub extern crate better_panic; +pub extern crate unicode_width; +#[cfg(feature = "sing")] pub extern crate jack; +#[cfg(feature = "midi")] pub extern crate midly; +#[cfg(feature = "term")] pub extern crate ratatui; +#[cfg(feature = "term")] pub extern crate crossterm; +#[cfg(feature = "lang")] pub extern crate dizzle; +#[cfg(test)] #[macro_use] pub extern crate proptest; +#[cfg(test)] pub(crate) use proptest_derive::Arbitrary; + +pub(crate) use ::{ + std::fmt::{Debug, Display}, + std::ops::{Add, Sub, Mul, Div}, + std::sync::{Arc, RwLock}, + std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::*}, + std::marker::PhantomData +}; + +#[cfg(feature = "lang")] pub use ::dizzle::{Usually, Perhaps}; +#[cfg(feature = "lang")] use ::dizzle::*; /// Define a trait an implement it for various mutation-enabled wrapper types. */ #[macro_export] macro_rules! flex_trait_mut ( @@ -68,32 +89,9 @@ mod deps; pub use self::deps::*; } /// Implement [`Debug`] in bulk. -#[macro_export] macro_rules! impl_debug ( - (<$($T:ident $(: $U:ident)?),+> $S:ty|$self:ident,$w:ident|$body:block)=>{ - impl <$($T$(:$U)?),+> std::fmt::Debug for $S { - fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body - } - }; - ($S:ty|$self:ident,$w:ident|$body:block)=>{ - impl std::fmt::Debug for $S { - fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body - } - }; -); - -/// Implement [`Display`] in bulk. -#[macro_export] macro_rules! impl_display ( - (<$($T:ident $(: $U:ident)?),+> $S:ty|$self:ident,$w:ident|$body:block)=>{ - impl <$($T$(:$U)?),+> std::fmt::Display for $S { - fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body - } - }; - ($S:ty|$self:ident,$w:ident|$body:block)=>{ - impl std::fmt::Display for $S { - fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body - } - }; -); +#[macro_export] macro_rules! impl_debug (($($S:ty|$self:ident,$w:ident|$body:block)*)=>{ + $(impl std::fmt::Debug for $S { fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body })* +}); /// Implement [`From`] in bulk. #[macro_export] macro_rules! impl_from ( @@ -303,7 +301,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } } /// Run something with the client. pub fn with_client (&self, op: impl FnOnce(&Client)->T) -> T { - match &*self.0.try_read().unwrap() { + match &*self.0.read().unwrap() { Inert => panic!("jack client not activated"), Inactive(client) => op(client), Activating => panic!("jack client has not finished activation"), @@ -316,14 +314,14 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } let client_state = self.0.clone(); let app: Arc> = Arc::new(RwLock::new(init(self)?)); let mut state = Activating; - std::mem::swap(&mut*client_state.try_write().unwrap(), &mut state); + std::mem::swap(&mut*client_state.write().unwrap(), &mut state); if let Inactive(client) = state { // This is the misc notifications handler. It's a struct that wraps a [Box] // which performs type erasure on a callback that takes [JackEvent], which is // one of the available misc notifications. let notify = JackNotify(Box::new({ let app = app.clone(); - move|event|(&mut*app.try_write().unwrap()).handle(event) + move|event|(&mut*app.write().unwrap()).handle(event) }) as BoxedJackEventHandler); // This is the main processing handler. It's a struct that wraps a [Box] // which performs type erasure on a callback that takes [Client] and [ProcessScope] @@ -331,14 +329,14 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } // implements audio and MIDI input and output on a realtime basis. let process = ::jack::contrib::ClosureProcessHandler::new(Box::new({ let app = app.clone(); - move|c: &_, s: &_|if let Some(mut app) = app.try_write() { + move|c: &_, s: &_|if let Ok(mut app) = app.write() { app.process(c, s) } else { Control::Quit } }) as BoxedAudioHandler); // Launch a client with the two handlers. - *client_state.try_write().unwrap() = Active( + *client_state.write().unwrap() = Active( client.activate_async(notify, process)? ); } else { @@ -468,7 +466,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } fn callback ( state: &Arc>, client: &Client, scope: &ProcessScope ) -> Control where Self: Sized { - if let Some(mut state) = state.try_write() { + if let Ok(mut state) = state.write() { state.process(client, scope) } else { Control::Quit @@ -635,10 +633,10 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } for connect in self.connections().iter() { match &connect.name { Some(Exact(name)) => { - *connect.status.try_write().unwrap() = self.connect_exact(name)?; + *connect.status.write().unwrap() = self.connect_exact(name)?; }, Some(RegExp(re)) => { - *connect.status.try_write().unwrap() = self.connect_regexp(re, connect.scope)?; + *connect.status.write().unwrap() = self.connect_regexp(re, connect.scope)?; }, _ => {}, }; @@ -945,7 +943,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } self.output_buffer[sample].push(self.note_buffer.clone()); // Update the list of currently held notes. if let LiveEvent::Midi { ref message, .. } = event { - update_keys(&mut*self.held.try_write().unwrap(), message); + update_keys(&mut*self.held.write().unwrap(), message); } } /// Write a chunk of MIDI data from the output buffer to the output port. @@ -1102,7 +1100,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } pub fn info (&self) -> Arc { format!(" ({}) {} {}", { - let status = self.status.try_read().unwrap(); + let status = self.status.read().unwrap(); let mut ok = 0; for (_, _, state) in status.iter() { if *state == Connected { @@ -1190,8 +1188,6 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } use crate::time::PerfModel; #[derive(Debug)] pub struct Task { - /// Human-friendly name - pub name: Arc, /// Exit flag. pub exit: Arc, /// Performance counter. @@ -1202,37 +1198,30 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } impl Task { /// Spawn a TUI thread that runs `callt least one, then repeats until `exit`. - pub fn new () + Send + Sync + 'static> ( - name: Option>, - exit: Arc, - mut call: F - ) -> Result { + pub fn new (exit: Arc, mut call: F) -> Result + where F: FnMut(&PerfModel)->() + Send + Sync + 'static + { let perf = Arc::new(PerfModel::default()); - let name: Arc = name.map(|x|x.as_ref().into()).unwrap_or_else(||"tengri".into()); Ok(Self { exit: exit.clone(), perf: perf.clone(), - join: Builder::new().name(name.as_ref().into()).spawn(move || { + join: Builder::new().name("tengri task".into()).spawn(move || { #[cfg(feature = "prof")] profiling::register_thread!(); while !exit.fetch_and(true, Relaxed) { let _ = perf.cycle(&mut call); } - })?.into(), - name + })?.into() }) } /// Spawn a thread that runs `call` least one, then repeats /// until `exit`, sleeping for `time` msec after every iteration. pub fn new_sleep ( - name: Option>, - exit: Arc, - time: Duration, - mut call: F + exit: Arc, time: Duration, mut call: F ) -> Result where F: FnMut(&PerfModel)->() + Send + Sync + 'static { - Self::new(name, exit, move |perf| { + Self::new(exit, move |perf| { let _ = call(perf); sleep(time); }) @@ -1241,14 +1230,11 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } /// Spawn a thread that uses [crossterm::event::poll] /// to run `call` every `time` msec. #[cfg(feature = "term")] pub fn new_poll ( - name: Option>, - exit: Arc, - time: Duration, - mut call: F + exit: Arc, time: Duration, mut call: F ) -> Result where F: FnMut(&PerfModel)->() + Send + Sync + 'static { - Self::new(name, exit, move |perf| { + Self::new(exit, move |perf| { if poll(time).is_ok() { let _ = call(perf); } @@ -1401,19 +1387,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } } } - impl> Draw for Arc { - fn draw (&self, to: &mut S) -> Drawn { - (**self).draw(to) - } - } - - impl> Draw for Box { - fn draw (&self, to: &mut S) -> Drawn { - (**self).draw(to) - } - } - - impl> Draw for Option { + impl<'a, S: Screen, D: Draw> Draw for Option { fn draw (&self, to: &mut S) -> Drawn { self.as_ref().map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default) } @@ -1425,6 +1399,12 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } //} //} + //impl> Draw for Arc { + //fn draw (&self, __: &mut T) -> Perhaps> { + //todo!() + //} + //} + impl<'a, T: Screen, V: Draw> Draw for &V { fn draw (&self, to: &mut T) -> Drawn { (*self).draw(to) diff --git a/src/term.rs b/src/term.rs index 8b19db3..f4b739b 100644 --- a/src/term.rs +++ b/src/term.rs @@ -162,11 +162,11 @@ impl Tui { ) -> Result { let exited = exited.clone(); let state = state.clone(); - Task::new_poll(Some("tengri input"), exited.clone(), poll, move |_| { + Task::new_poll(exited.clone(), poll, move |_| { let event = read().unwrap(); if Exit::is(&event) { exited.store(true, Relaxed); - } else if let Err(e) = state.write().apply(&TuiEvent(event)) { + } else if let Err(e) = state.write().unwrap().apply(&TuiEvent(event)) { panic!("{e}") } }) @@ -268,15 +268,15 @@ impl Tui { let Size { width, height } = backend.size().expect("get size failed"); let mut prev = Tui::new(width, height); let mut next = Tui::new(width, height); - Ok(Task::new_sleep(Some("tengri output"), exited.clone(), sleep, move |perf| { + Ok(Task::new_sleep(exited.clone(), sleep, move |perf| { let Size { width, height } = backend.size().expect("get size failed"); - if let Some(state) = state.try_read() { + if let Ok(state) = state.try_read() { prev.resize(&mut backend, width, height); state.draw(&mut next).expect("draw failed"); // TODO draw error prev.redraw(&mut backend, &mut next); } - //let timer = format!("{:>3.3}ms", perf.used.load(Relaxed)); - //prev.blit(&timer, 0, 0, Some(Style::default())); + let timer = format!("{:>3.3}ms", perf.used.load(Relaxed)); + prev.blit(&timer, 0, 0, Some(Style::default())); })?) } /// Draw TUI content or its error message.