use super::{BackgroundTask, StatusUpdateRequest};
use crate::system::{Handle, SystemEvent};
use std::sync::{Arc, Condvar, Mutex};
pub struct BackgroundTaskConector<T: Send + 'static, R: Send + 'static> {
handle: Handle<BackgroundTask<T, R>>,
sysevent_sender: std::sync::mpsc::Sender<SystemEvent>,
sender: std::sync::mpsc::Sender<T>,
receiver: std::sync::mpsc::Receiver<R>,
state: Arc<(Mutex<StatusUpdateRequest>, Condvar)>,
}
impl<T, R> BackgroundTaskConector<T, R>
where
T: Send + 'static,
R: Send + 'static,
{
pub(super) fn new(
handle: Handle<BackgroundTask<T, R>>,
sysevent_sender: std::sync::mpsc::Sender<SystemEvent>,
sender: std::sync::mpsc::Sender<T>,
receiver: std::sync::mpsc::Receiver<R>,
state: Arc<(Mutex<StatusUpdateRequest>, Condvar)>,
) -> Self {
Self {
handle,
sysevent_sender,
sender,
receiver,
state,
}
}
pub fn notify(&self, data: T) -> bool {
if self.sender.send(data).is_err() {
return false;
}
self.sysevent_sender.send(SystemEvent::BackgroundTaskNotify(self.handle.cast())).is_ok()
}
pub(super) fn notify_start(&self) {
let _ = self.sysevent_sender.send(SystemEvent::BackgroundTaskStart(self.handle.cast()));
}
pub(super) fn notify_end(&self) {
let _ = self.sysevent_sender.send(SystemEvent::BackgroundTaskEnd(self.handle.cast()));
}
pub fn query(&self, data: T) -> Option<R> {
if self.sender.send(data).is_err() {
return None;
}
if self.sysevent_sender.send(SystemEvent::BackgroundTaskQuery(self.handle.cast())).is_err() {
return None;
}
self.receiver.recv().ok()
}
pub fn should_stop(&self) -> bool {
let (lock, cvar) = &*self.state;
let mut status = lock.lock().unwrap();
match *status {
StatusUpdateRequest::None => false,
StatusUpdateRequest::Pause => {
status = cvar.wait_while(status, |s| *s == StatusUpdateRequest::Pause).unwrap();
*status == StatusUpdateRequest::Close
}
StatusUpdateRequest::Close => true,
}
}
}