use std::sync::{Arc, Mutex, RwLock};
use std::boxed::FnBox;
use rayon::ThreadPool;
use crate::files::{File, Files, Kind};
use crate::fscache::FsCache;
use crate::listview::ListView;
use crate::textview::TextView;
use crate::widget::{Widget, WidgetCore};
use crate::coordinates::Coordinates;
use crate::fail::{HResult, HError, ErrorLog};
use crate::dirty::Dirtyable;
pub type AsyncValueFn<T> = Box<dyn FnBox(Stale) -> HResult<T> + Send + Sync>;
pub type AsyncValue<T> = Arc<Mutex<Option<HResult<T>>>>;
pub type AsyncReadyFn = Box<dyn FnBox() -> HResult<()> + Send + Sync>;
pub type AsyncWidgetFn<W> = Box<dyn FnBox(Stale, WidgetCore)
-> HResult<W> + Send + Sync>;
type WidgetO = Box<dyn Widget + Send>;
lazy_static! {
static ref SUBPROC: Arc<Mutex<Option<u32>>> = { Arc::new(Mutex::new(None)) };
}
fn kill_proc() -> HResult<()> {
let mut pid = SUBPROC.lock()?;
pid.map(|pid|
unsafe { libc::kill(pid as i32, 15); }
);
*pid = None;
Ok(())
}
#[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)
}
use std::fmt::{Debug, Formatter};
impl<T: Send + Debug> Debug for Async<T> {
fn fmt(&self, formatter: &mut Formatter) -> Result<(), std::fmt::Error> {
write!(formatter,
"{:?}, {:?} {:?}",
self.value,
self.async_value,
self.stale)
}
}
#[derive(Clone)]
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>>>,
started: bool,
stale: Stale,
}
impl<T: Send + 'static> Async<T> {
pub fn new(closure: AsyncValueFn<T>)
-> 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)),
started: 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)),
started: false,
stale: stale };
async_value
}
pub fn new_with_value(val: T) -> Async<T> {
Async {
value: Ok(val),
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_async(async_fn: Arc<Mutex<Option<AsyncValueFn<T>>>>,
async_value: AsyncValue<T>,
on_ready_fn: Arc<Mutex<Option<AsyncReadyFn>>>,
stale: Stale) -> HResult<()> {
let value_fn = async_fn.lock()?.take()?;
let value = value_fn.call_box((stale.clone(),));
async_value.lock()?.replace(value);
on_ready_fn.lock()?
.take()
.map(|on_ready| on_ready.call_box(()).log());
Ok(())
}
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 || {
Async::run_async(closure,
async_value,
on_ready_fn,
stale).log();
});