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:
parent
90e626d169
commit
8d8d9631b5
@ -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)
|
||||
}
|
||||
|
12
src/files.rs
12
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(())
|
||||
}
|
||||
|
@ -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(())
|
||||
}));
|
||||
|
Loading…
x
Reference in New Issue
Block a user