refactor: progress bar

Change threading to use channels instead of atomic boolean

Allows for early exit so we don't have to wait for spinner loop timeout
This commit is contained in:
andy.boot
2023-01-19 19:49:18 +00:00
parent 3fd78490e6
commit 4242363f40
+12 -11
View File
@@ -3,6 +3,7 @@ use std::{
path::Path, path::Path,
sync::{ sync::{
atomic::{AtomicBool, AtomicU64, AtomicU8, AtomicUsize, Ordering}, atomic::{AtomicBool, AtomicU64, AtomicU8, AtomicUsize, Ordering},
mpsc::{self, RecvTimeoutError, Sender},
Arc, RwLock, Arc, RwLock,
}, },
thread::JoinHandle, thread::JoinHandle,
@@ -78,15 +79,13 @@ fn format_indicator_str(data: &PAtomicInfo, progress_char_i: usize, status: &str
} }
pub struct PIndicator { pub struct PIndicator {
thread_run: Arc<AtomicBool>, pub thread: Option<(Sender<()>, JoinHandle<()>)>,
pub thread: Option<JoinHandle<()>>,
pub data: Arc<PAtomicInfo>, pub data: Arc<PAtomicInfo>,
} }
impl PIndicator { impl PIndicator {
pub fn build_me() -> Self { pub fn build_me() -> Self {
Self { Self {
thread_run: Arc::new(AtomicBool::new(true)),
thread: None, thread: None,
data: Arc::new(PAtomicInfo { data: Arc::new(PAtomicInfo {
..Default::default() ..Default::default()
@@ -96,14 +95,17 @@ impl PIndicator {
pub fn spawn(&mut self, is_iso: bool) { pub fn spawn(&mut self, is_iso: bool) {
let data = self.data.clone(); let data = self.data.clone();
let is_building_data_const = self.thread_run.clone(); let (stop_handler, receiver) = mpsc::channel::<()>();
let time_info_thread = std::thread::spawn(move || { let time_info_thread = std::thread::spawn(move || {
let mut progress_char_i: usize = 0; let mut progress_char_i: usize = 0;
let mut stdout = std::io::stdout(); let mut stdout = std::io::stdout();
std::thread::sleep(Duration::from_millis(SPINNER_SLEEP_TIME));
while is_building_data_const.load(ORDERING) { // While the timeout triggers we go round the loop
// If we disconnect or the sender sends its message we exit the while loop
while let Err(RecvTimeoutError::Timeout) =
receiver.recv_timeout(Duration::from_millis(SPINNER_SLEEP_TIME))
{
let msg = match data.state.load(ORDERING) { let msg = match data.state.load(ORDERING) {
Operation::INDEXING => { Operation::INDEXING => {
let base = format_indicator_str(&data, progress_char_i, "Indexing"); let base = format_indicator_str(&data, progress_char_i, "Indexing");
@@ -126,7 +128,6 @@ impl PIndicator {
progress_char_i += 1; progress_char_i += 1;
progress_char_i %= PROGRESS_CHARS_LEN; progress_char_i %= PROGRESS_CHARS_LEN;
std::thread::sleep(Duration::from_millis(SPINNER_SLEEP_TIME));
// Clear the text written by 'write!' // Clear the text written by 'write!'
print!("\r{:width$}", " ", width = msg.len()); print!("\r{:width$}", " ", width = msg.len());
} }
@@ -135,13 +136,13 @@ impl PIndicator {
print!("\r"); print!("\r");
stdout.flush().unwrap(); stdout.flush().unwrap();
}); });
self.thread = Some(time_info_thread) self.thread = Some((stop_handler, time_info_thread))
} }
pub fn stop(self) { pub fn stop(self) {
self.thread_run.store(false, ORDERING); if let Some((stop_handler, thread)) = self.thread {
if let Some(t) = self.thread { stop_handler.send(()).unwrap();
t.join().unwrap(); thread.join().unwrap();
} }
} }
} }