diff options
Diffstat (limited to 'src/preview.rs')
-rw-r--r-- | src/preview.rs | 165 |
1 files changed, 131 insertions, 34 deletions
diff --git a/src/preview.rs b/src/preview.rs index da2a90a..d70b011 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, RwLock}; use rayon::ThreadPool; @@ -10,8 +10,6 @@ use crate::coordinates::Coordinates; use crate::fail::{HResult, HError, ErrorLog}; -pub type Stale = Arc<Mutex<bool>>; - pub type AsyncValueFn<T> = Box<Fn(Stale) -> HResult<T> + Send>; pub type AsyncValue<T> = Arc<Mutex<Option<HResult<T>>>>; pub type AsyncReadyFn<T> = Box<Fn(&mut T) -> HResult<()> + Send>; @@ -33,8 +31,30 @@ fn kill_proc() -> HResult<()> { Ok(()) } -pub fn is_stale(stale: &Arc<Mutex<bool>>) -> HResult<bool> { - let stale = *(stale.lock().unwrap()); +#[derive(Clone, Debug)] +pub struct Stale(Arc<RwLock<bool>>); + +impl Stale { + pub fn new() -> Stale { + Stale(Arc::new(RwLock::new(false))) + } + pub fn is_stale(&self) -> HResult<bool> { + Ok(*self.0.read()?) + } + pub fn set_stale(&self) -> HResult<()> { + *self.0.write()? = true; + Ok(()) + } + pub fn set_fresh(&self) -> HResult<()> { + *self.0.write()? = false; + Ok(()) + } +} + + + +pub fn is_stale(stale: &Stale) -> HResult<bool> { + let stale = stale.is_stale()?; Ok(stale) } @@ -68,7 +88,20 @@ impl<T: Send + 'static> Async<T> { async_value: Arc::new(Mutex::new(None)), async_closure: Arc::new(Mutex::new(Some(closure))), on_ready: Arc::new(Mutex::new(None)), - stale: Arc::new(Mutex::new(false)) }; + stale: Stale::new() }; + + async_value + } + + pub fn new_with_stale(closure: AsyncValueFn<T>, + stale: Stale) + -> Async<T> { + let async_value = Async { + value: HError::async_not_ready(), + async_value: Arc::new(Mutex::new(None)), + async_closure: Arc::new(Mutex::new(Some(closure))), + on_ready: Arc::new(Mutex::new(None)), + stale: stale }; async_value } @@ -79,53 +112,104 @@ impl<T: Send + 'static> Async<T> { async_value: Arc::new(Mutex::new(None)), async_closure: Arc::new(Mutex::new(None)), on_ready: Arc::new(Mutex::new(None)), - stale: Arc::new(Mutex::new(false)) + stale: Stale::new() } } pub fn run(&mut self) -> HResult<()> { - let closure = self.async_closure.lock()?.take()?; + let closure = self.async_closure.clone(); let async_value = self.async_value.clone(); let stale = self.stale.clone(); - let on_ready_fn = self.on_ready.lock()?.take(); + let on_ready_fn = self.on_ready.clone(); std::thread::spawn(move|| -> HResult<()> { - let mut value = closure(stale); - - if let Ok(ref mut value) = value { - if let Some(on_ready_fn) = on_ready_fn { - on_ready_fn(value); + let value = closure.lock().map(|closure| + closure.as_ref().map(|closure| + closure(stale))); + + if let Ok(value) = value { + if let Some(value) = value { + match value { + Ok(mut value) => { + if let Ok(mut on_ready_fn) = on_ready_fn.lock() { + if let Some(on_ready_fn) = on_ready_fn.as_ref() { + on_ready_fn(&mut value).log(); + } + on_ready_fn.take(); + } + async_value + .lock() + .map(|mut async_value| + async_value.replace(Ok(value))).ok(); + closure.lock().map(|mut closure| + closure.take()).ok(); + }, + Err(err) => { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Err(err))).ok(); + } + } } + } else { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Err(HError::MutexError))).ok(); } - - async_value.lock()?.replace(value); Ok(()) }); Ok(()) } pub fn run_pooled(&mut self, pool: &ThreadPool) -> HResult<()> { - let closure = self.async_closure.lock()?.take()?; + let closure = self.async_closure.clone(); let async_value = self.async_value.clone(); let stale = self.stale.clone(); - let on_ready_fn = self.on_ready.lock()?.take(); + let on_ready_fn = self.on_ready.clone(); pool.spawn(move || { - let mut value = closure(stale); - - if let Ok(ref mut value) = value { - if let Some(on_ready_fn) = on_ready_fn { - on_ready_fn(value); + let value = closure.lock().map(|closure| + closure.as_ref().map(|closure| + closure(stale))); + + if let Ok(value) = value { + if let Some(value) = value { + match value { + Ok(mut value) => { + if let Ok(mut on_ready_fn) = on_ready_fn.lock() { + if let Some(on_ready_fn) = on_ready_fn.as_ref() { + on_ready_fn(&mut value).log(); + } + on_ready_fn.take(); + } + async_value + .lock() + .map(|mut async_value| + async_value.replace(Ok(value))).ok(); + closure.lock().map(|mut closure| + closure.take()).ok(); + }, + Err(err) => { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Err(err))).ok(); + } + } } + } else { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Err(HError::MutexError))).ok(); } - - async_value - .lock() - .map(|mut async_value| async_value.replace(value)); }); Ok(()) } + pub fn wait(&mut self) -> HResult<()> { let closure = self.async_closure.lock()?.take()?; let mut value = closure(self.stale.clone()); @@ -141,12 +225,21 @@ impl<T: Send + 'static> Async<T> { } pub fn set_stale(&mut self) -> HResult<()> { - *self.stale.lock()? = true; + self.stale.set_stale()?; + Ok(()) + } + + pub fn set_fresh(&self) -> HResult<()> { + self.stale.set_fresh()?; Ok(()) } pub fn is_stale(&self) -> HResult<bool> { - is_stale(&self.stale) + self.stale.is_stale() + } + + pub fn get_stale(&self) -> Stale { + self.stale.clone() } pub fn take_async(&mut self) -> HResult<()> { @@ -251,6 +344,10 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> { self.widget.is_stale() } + pub fn get_stale(&self) -> Stale { + self.widget.get_stale() + } + pub fn widget(&self) -> HResult<&W> { self.widget.get() } @@ -292,7 +389,7 @@ impl<T: Widget + Send + 'static> Widget for AsyncWidget<T> { } fn refresh(&mut self) -> HResult<()> { - self.widget.take_async().log(); + self.widget.take_async().ok(); let coords = self.get_coordinates()?.clone(); if let Ok(widget) = self.widget_mut() { @@ -342,7 +439,7 @@ pub struct Previewer { core: WidgetCore, file: Option<File>, selection: Option<File>, - cached_files: Option<Files> + cached_files: Option<Files>, } @@ -435,7 +532,7 @@ impl Previewer { selection: Option<File>, cached_files: Option<Files>, core: &WidgetCore, - stale: Arc<Mutex<bool>>) + stale: Stale) -> Result<WidgetO, HError> { let files = cached_files.or_else(|| { Files::new_from_path_cancellable(&file.path, @@ -456,7 +553,7 @@ impl Previewer { Ok(Box::new(file_list) as Box<dyn Widget + Send>) } - fn preview_text(file: &File, core: &WidgetCore, stale: Arc<Mutex<bool>>) + fn preview_text(file: &File, core: &WidgetCore, stale: Stale) -> HResult<WidgetO> { let lines = core.coordinates.ysize() as usize; let mut textview @@ -476,7 +573,7 @@ impl Previewer { fn preview_external(file: &File, core: &WidgetCore, - stale: Arc<Mutex<bool>>) + stale: Stale) -> Result<Box<dyn Widget + Send>, HError> { let process = std::process::Command::new("scope.sh") |