1
0
mirror of https://github.com/bobwen-dev/hunter synced 2025-04-12 00:55:41 +02:00

fixed possibler race condition

This commit is contained in:
rabite 2019-03-26 13:05:15 +01:00
parent 90e626d169
commit 8d8d9631b5
3 changed files with 55 additions and 25 deletions

View File

@ -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)
}

View File

@ -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(())
}

View File

@ -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) => {
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();
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().log();
}
on_ready_fn.take();
}
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) => {
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();
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().log();
}
on_ready_fn.take();
}
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(())
}));