From 8d8d9631b5fce48e2e65410aa4d0df64948f5ad8 Mon Sep 17 00:00:00 2001 From: rabite Date: Tue, 26 Mar 2019 13:05:15 +0100 Subject: fixed possibler race condition --- src/fail.rs | 6 ++++++ src/files.rs | 12 ++++++------ src/preview.rs | 58 +++++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 53 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/fail.rs b/src/fail.rs index 55cd5aa..c85028c 100644 --- a/src/fail.rs +++ b/src/fail.rs @@ -43,6 +43,8 @@ pub enum HError { AsyncStaleError, #[fail(display = "Value has already been taken!")] AsyncAlreadyTakenError, + #[fail(display = "Async has already been started!")] + AsyncAlreadyStartedError, #[fail(display = "Async Error: {}", _0)] AsyncError(String), #[fail(display = "No widget found")] @@ -149,6 +151,10 @@ impl HError { Err(HError::AsyncError(format!("{}", error))) } + pub fn async_started() -> HResult { + Err(HError::AsyncAlreadyStartedError) + } + pub fn metadata_processed() -> HResult { Err(HError::MetadataProcessedError) } diff --git a/src/files.rs b/src/files.rs index 90646ba..8b3265c 100644 --- a/src/files.rs +++ b/src/files.rs @@ -379,14 +379,13 @@ impl Files { self.dirty_meta.set_clean(); let meta_pool = make_pool(sender.clone()); - let dirsize_pool = make_pool(sender); for file in self.files.iter_mut().take(meta_files) { if !file.meta_processed { file.take_meta(&meta_pool).ok(); } - if file.is_dir() { - file.take_dirsize(&dirsize_pool).ok(); + if file.is_dir() && file.meta_processed { + file.take_dirsize(&meta_pool).ok(); } } @@ -568,7 +567,7 @@ impl File { None => Async::new(meta_closure) }; if let Some(dirty_meta) = dirty_meta { - meta.on_ready(Box::new(move |_| { + meta.on_ready(Box::new(move || { let mut dirty_meta = dirty_meta.clone(); dirty_meta.set_dirty(); @@ -594,7 +593,7 @@ impl File { }; if let Some(dirty_meta) = dirty_meta { - dirsize.on_ready(Box::new(move |_| { + dirsize.on_ready(Box::new(move || { let mut dirty_meta = dirty_meta.clone(); dirty_meta.set_dirty(); @@ -650,14 +649,15 @@ impl File { } pub fn reload_meta(&mut self) -> HResult<()> { - self.dirty_meta.as_mut()?.set_dirty(); self.meta_processed = false; self.meta = File::make_async_meta(&self.path, self.dirty_meta.clone(), None); + self.meta.run(); if self.dirsize.is_some() { self.dirsize = Some(File::make_async_dirsize(&self.path, self.dirty_meta.clone(), None)); + self.dirsize.as_mut()?.run(); } Ok(()) } diff --git a/src/preview.rs b/src/preview.rs index d70b011..2bfeb0e 100644 --- a/src/preview.rs +++ b/src/preview.rs @@ -12,7 +12,7 @@ use crate::fail::{HResult, HError, ErrorLog}; pub type AsyncValueFn = Box HResult + Send>; pub type AsyncValue = Arc>>>; -pub type AsyncReadyFn = Box HResult<()> + Send>; +pub type AsyncReadyFn = Box HResult<()> + Send>; pub type AsyncWidgetFn = Box HResult + Send>; @@ -76,8 +76,9 @@ pub struct Async { pub value: HResult, async_value: AsyncValue, async_closure: Arc>>>, - on_ready: Arc>>>, - stale: Stale + on_ready: Arc>>, + started: bool, + stale: Stale, } impl Async { @@ -88,6 +89,7 @@ impl Async { async_value: Arc::new(Mutex::new(None)), async_closure: Arc::new(Mutex::new(Some(closure))), on_ready: Arc::new(Mutex::new(None)), + started: false, stale: Stale::new() }; async_value @@ -101,6 +103,7 @@ impl Async { async_value: Arc::new(Mutex::new(None)), async_closure: Arc::new(Mutex::new(Some(closure))), on_ready: Arc::new(Mutex::new(None)), + started: false, stale: stale }; async_value @@ -112,15 +115,21 @@ impl Async { async_value: Arc::new(Mutex::new(None)), async_closure: Arc::new(Mutex::new(None)), on_ready: Arc::new(Mutex::new(None)), + started: false, stale: Stale::new() } } pub fn run(&mut self) -> HResult<()> { + if self.started { + HError::async_started()? + } + 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.clone(); + self.started = true; std::thread::spawn(move|| -> HResult<()> { let value = closure.lock().map(|closure| @@ -131,16 +140,18 @@ impl Async { if let Some(value) = value { match value { Ok(mut value) => { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Ok(value))).ok(); + 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().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(); }, @@ -164,10 +175,15 @@ impl Async { } pub fn run_pooled(&mut self, pool: &ThreadPool) -> HResult<()> { + if self.started { + HError::async_started()? + } + 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.clone(); + self.started = true; pool.spawn(move || { let value = closure.lock().map(|closure| @@ -178,16 +194,16 @@ impl Async { if let Some(value) = value { match value { Ok(mut value) => { + async_value + .lock() + .map(|mut async_value| + async_value.replace(Ok(value))).ok(); 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().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(); }, @@ -217,7 +233,7 @@ impl Async { if let Ok(ref mut value) = value { - on_ready_fn.map(|on_ready_fn| on_ready_fn(value)); + on_ready_fn.map(|on_ready_fn| on_ready_fn()); } self.value = value; @@ -242,6 +258,14 @@ impl Async { self.stale.clone() } + pub fn is_started(&self) -> bool { + self.started + } + + pub fn set_unstarted(&mut self) { + self.started = false; + } + pub fn take_async(&mut self) -> HResult<()> { if self.value.is_ok() { HError::async_taken()? } @@ -278,7 +302,7 @@ impl Async { } pub fn on_ready(&mut self, - fun: AsyncReadyFn) { + fun: AsyncReadyFn) { *self.on_ready.lock().unwrap() = Some(fun); } } @@ -304,7 +328,7 @@ impl AsyncWidget { pub fn new(core: &WidgetCore, closure: AsyncValueFn) -> AsyncWidget { let sender = core.get_sender(); let mut widget = Async::new(Box::new(move |stale| closure(stale))); - widget.on_ready(Box::new(move |_| { + widget.on_ready(Box::new(move || { sender.send(crate::widget::Events::WidgetReady)?; Ok(()) })); @@ -325,7 +349,7 @@ impl AsyncWidget { closure(stale, core.clone()) })); - widget.on_ready(Box::new(move |_| { + widget.on_ready(Box::new(move || { sender.send(crate::widget::Events::WidgetReady)?; Ok(()) })); -- cgit v1.2.3