106 lines
2.4 KiB
Rust
106 lines
2.4 KiB
Rust
|
|
use crate::fl;
|
||
|
|
|
||
|
|
use std::sync::{Arc, Condvar, Mutex};
|
||
|
|
|
||
|
|
#[derive(Clone, Copy, Debug)]
|
||
|
|
pub enum ControllerState {
|
||
|
|
Cancelled,
|
||
|
|
Paused,
|
||
|
|
Running,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug)]
|
||
|
|
struct ControllerInner {
|
||
|
|
state: Mutex<ControllerState>,
|
||
|
|
progress: Mutex<f32>,
|
||
|
|
condvar: Condvar,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[derive(Debug)]
|
||
|
|
pub struct Controller {
|
||
|
|
primary: bool,
|
||
|
|
inner: Arc<ControllerInner>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Controller {
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
primary: true,
|
||
|
|
inner: Arc::new(ControllerInner {
|
||
|
|
state: Mutex::new(ControllerState::Running),
|
||
|
|
progress: Mutex::new(0.0),
|
||
|
|
condvar: Condvar::new(),
|
||
|
|
}),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn check(&self) -> Result<(), String> {
|
||
|
|
let mut state = self.inner.state.lock().unwrap();
|
||
|
|
loop {
|
||
|
|
match *state {
|
||
|
|
ControllerState::Cancelled => return Err(fl!("cancelled")),
|
||
|
|
ControllerState::Paused => {
|
||
|
|
state = self.inner.condvar.wait(state).unwrap();
|
||
|
|
}
|
||
|
|
ControllerState::Running => return Ok(()),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn progress(&self) -> f32 {
|
||
|
|
*self.inner.progress.lock().unwrap()
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_progress(&self, progress: f32) {
|
||
|
|
*self.inner.progress.lock().unwrap() = progress;
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn state(&self) -> ControllerState {
|
||
|
|
*self.inner.state.lock().unwrap()
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_state(&self, state: ControllerState) {
|
||
|
|
*self.inner.state.lock().unwrap() = state;
|
||
|
|
self.inner.condvar.notify_all();
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn is_cancelled(&self) -> bool {
|
||
|
|
matches!(self.state(), ControllerState::Cancelled)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn cancel(&self) {
|
||
|
|
self.set_state(ControllerState::Cancelled);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn is_paused(&self) -> bool {
|
||
|
|
matches!(self.state(), ControllerState::Paused)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn pause(&self) {
|
||
|
|
self.set_state(ControllerState::Paused);
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn unpause(&self) {
|
||
|
|
//TODO: ensure this does not override Cancel?
|
||
|
|
self.set_state(ControllerState::Running);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Clone for Controller {
|
||
|
|
fn clone(&self) -> Self {
|
||
|
|
Self {
|
||
|
|
primary: false,
|
||
|
|
inner: self.inner.clone(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Drop for Controller {
|
||
|
|
fn drop(&mut self) {
|
||
|
|
// Cancel operations if primary controller is dropped
|
||
|
|
if self.primary {
|
||
|
|
self.cancel();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|