summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-03-26 13:05:15 +0100
committerrabite <rabite@posteo.de>2019-03-26 13:05:15 +0100
commit8d8d9631b5fce48e2e65410aa4d0df64948f5ad8 (patch)
tree737a4f787ace9f2ee01cb0f65c4cbd8280600d63
parent90e626d16902f2dfcaf50121325913c579583bca (diff)
fixed possibler race condition
-rw-r--r--src/fail.rs6
-rw-r--r--src/files.rs12
-rw-r--r--src/preview.rs58
3 files changed, 53 insertions, 23 deletions
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<T>() -> HResult<T> {
+ Err(HError::AsyncAlreadyStartedError)
+ }
+
pub fn metadata_processed<T>() -> HResult<T> {
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<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>;
+pub type AsyncReadyFn = Box<Fn() -> HResult<()> + Send>;
pub type AsyncWidgetFn<W> = Box<Fn(Stale, WidgetCore) -> HResult<W> + Send>;
@@ -76,8 +76,9 @@ pub struct Async<T: Send> {
pub value: HResult<T>,
async_value: AsyncValue<T>,
async_closure: Arc<Mutex<Option<AsyncValueFn<T>>>>,
- on_ready: Arc<Mutex<Option<AsyncReadyFn<T>>>>,
- stale: Stale
+ on_ready: Arc<Mutex<Option<AsyncReadyFn>>>,
+ started: bool,
+ stale: Stale,
}
impl<T: Send + 'static> Async<T> {
@@ -88,6 +89,7 @@ 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)),
+ started: false,
stale: Stale::new() };
async_value
@@ -101,6 +103,7 @@ 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)),
+ started: false,
stale: stale };
async_value
@@ -112,15 +115,21 @@ 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)),
+ 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<T: Send + 'static> Async<T> {
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<T: Send + 'static> Async<T> {
}
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<T: Send + 'static> Async<T> {
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<T: Send + 'static> Async<T> {
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<T: Send + 'static> Async<T> {
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<T: Send + 'static> Async<T> {
}
pub fn on_ready(&mut self,
- fun: AsyncReadyFn<T>) {
+ fun: AsyncReadyFn) {
*self.on_ready.lock().unwrap() = Some(fun);
}
}
@@ -304,7 +328,7 @@ impl<W: Widget + Send + 'static> AsyncWidget<W> {
pub fn new(core: &WidgetCore, closure: AsyncValueFn<W>) -> AsyncWidget<W> {
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<W: Widget + Send + 'static> AsyncWidget<W> {
closure(stale, core.clone())
}));
- widget.on_ready(Box::new(move |_| {
+ widget.on_ready(Box::new(move || {
sender.send(crate::widget::Events::WidgetReady)?;
Ok(())
}));