From d21342ae016e1bf184f9e7a864a65c57bdbdadda Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Fri, 8 Dec 2023 11:38:12 -0500 Subject: [PATCH 1/6] Add support for ignoring timing delay for first n lines Enables the activity to look 'in progress' immediately upon execution --- src/args.rs | 13 +++++++++++++ src/io.rs | 14 ++++++++++++-- src/lib.rs | 1 + src/main.rs | 3 ++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/args.rs b/src/args.rs index 54e046a46..fe1cab974 100644 --- a/src/args.rs +++ b/src/args.rs @@ -12,6 +12,15 @@ fn parse_speed_factor(s: &str) -> Result { Ok(value_as_float) } +#[cfg(not(target_arch = "wasm32"))] +fn parse_instant_print(s: &str) -> Result { + let value_as_int = s.parse::().map_err(|e| e.to_string())?; + if value_as_int < 0 { + return Err("Number of instant-print lines must be non-negative".to_string()); + } + Ok(value_as_int) +} + #[cfg(not(target_arch = "wasm32"))] fn parse_min_1(s: &str) -> Result { let value_as_u32 = s.parse::().map_err(|e| e.to_string())?; @@ -37,6 +46,10 @@ pub struct AppConfig { #[clap(short, long, default_value = "1", value_parser = parse_speed_factor)] pub speed_factor: f32, + /// Instantly print this many lines + #[clap(short, long = "instant-print-lines", default_value = "0", value_parser = parse_instant_print)] + pub instant_print_lines: i32, + /// Exit after running for this long (format example: 2h10min) #[clap(long, value_parser = humantime::parse_duration)] pub exit_after_time: Option, diff --git a/src/io.rs b/src/io.rs index 1910be5dc..2597f6311 100644 --- a/src/io.rs +++ b/src/io.rs @@ -7,13 +7,23 @@ use wasm_bindgen::prelude::*; use std::io::{stdout, Write}; use crate::SPEED_FACTOR; +use crate::INSTANT_PRINT_LINES; + +static mut COUNTER: i32 = 0; #[cfg(not(target_arch = "wasm32"))] pub async fn csleep(length: u64) { use std::time; + let speed_factor = *SPEED_FACTOR.lock().await; - let sleep_length = time::Duration::from_millis((1.0 / speed_factor * length as f32) as u64); - async_std::task::sleep(sleep_length).await; + unsafe { COUNTER += 1; + let sleep_length = if COUNTER <= *INSTANT_PRINT_LINES.lock().await { + time::Duration::new(0, 0) + } else { + time::Duration::from_millis((1.0 / speed_factor * length as f32) as u64) + }; + async_std::task::sleep(sleep_length).await; + }; } #[cfg(target_arch = "wasm32")] diff --git a/src/lib.rs b/src/lib.rs index c2b706c56..d6a4929ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ use modules::{Module, ALL_MODULES}; lazy_static::lazy_static! { pub static ref CTRLC_PRESSED: AtomicBool = AtomicBool::new(false); pub static ref SPEED_FACTOR: Mutex = Mutex::new(1.0); + pub static ref INSTANT_PRINT_LINES: Mutex = Mutex::new(0); pub static ref STARTED_AT: Instant = Instant::now(); pub static ref MODULES_RAN: AtomicU32 = AtomicU32::new(0); } diff --git a/src/main.rs b/src/main.rs index 1caa252b2..2b93dde5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::Result; use genact::args::parse_args; -use genact::{run, SPEED_FACTOR}; +use genact::{run, SPEED_FACTOR, INSTANT_PRINT_LINES}; #[cfg(not(target_arch = "wasm32"))] use genact::exit_handler; @@ -32,6 +32,7 @@ async fn main() -> Result<()> { } *SPEED_FACTOR.lock().await = appconfig.speed_factor; + *INSTANT_PRINT_LINES.lock().await = appconfig.instant_print_lines; if appconfig.list_modules_and_exit { println!("Available modules:"); From 2616c7638b0df1166edded4ddd3b59b2e2e83256 Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Fri, 8 Dec 2023 12:21:34 -0500 Subject: [PATCH 2/6] Switch counter to AtomicU32 --- src/args.rs | 9 +++------ src/io.rs | 21 +++++++++++---------- src/lib.rs | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/args.rs b/src/args.rs index fe1cab974..5092b3e7e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -13,11 +13,8 @@ fn parse_speed_factor(s: &str) -> Result { } #[cfg(not(target_arch = "wasm32"))] -fn parse_instant_print(s: &str) -> Result { - let value_as_int = s.parse::().map_err(|e| e.to_string())?; - if value_as_int < 0 { - return Err("Number of instant-print lines must be non-negative".to_string()); - } +fn parse_instant_print(s: &str) -> Result { + let value_as_int = s.parse::().map_err(|e| e.to_string())?; Ok(value_as_int) } @@ -48,7 +45,7 @@ pub struct AppConfig { /// Instantly print this many lines #[clap(short, long = "instant-print-lines", default_value = "0", value_parser = parse_instant_print)] - pub instant_print_lines: i32, + pub instant_print_lines: u32, /// Exit after running for this long (format example: 2h10min) #[clap(long, value_parser = humantime::parse_duration)] diff --git a/src/io.rs b/src/io.rs index 2597f6311..07d54a5c5 100644 --- a/src/io.rs +++ b/src/io.rs @@ -6,24 +6,25 @@ use wasm_bindgen::prelude::*; #[cfg(not(target_arch = "wasm32"))] use std::io::{stdout, Write}; -use crate::SPEED_FACTOR; -use crate::INSTANT_PRINT_LINES; +use crate::{SPEED_FACTOR, INSTANT_PRINT_LINES}; -static mut COUNTER: i32 = 0; +use std::sync::atomic::{AtomicU32, Ordering}; +static COUNTER: AtomicU32 = AtomicU32::new(0); #[cfg(not(target_arch = "wasm32"))] pub async fn csleep(length: u64) { use std::time; let speed_factor = *SPEED_FACTOR.lock().await; - unsafe { COUNTER += 1; - let sleep_length = if COUNTER <= *INSTANT_PRINT_LINES.lock().await { - time::Duration::new(0, 0) - } else { - time::Duration::from_millis((1.0 / speed_factor * length as f32) as u64) - }; - async_std::task::sleep(sleep_length).await; + let count = COUNTER.fetch_add(1, Ordering::Relaxed); + let sleep_length = if count < *INSTANT_PRINT_LINES.lock().await { + // If user passed `--instant-print-lines`, there should be + // no pauses in first `INSTANT_PRINT_LINES` number of lines + time::Duration::new(0, 0) + } else { + time::Duration::from_millis((1.0 / speed_factor * length as f32) as u64) }; + async_std::task::sleep(sleep_length).await; } #[cfg(target_arch = "wasm32")] diff --git a/src/lib.rs b/src/lib.rs index d6a4929ba..9510fcddd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ use modules::{Module, ALL_MODULES}; lazy_static::lazy_static! { pub static ref CTRLC_PRESSED: AtomicBool = AtomicBool::new(false); pub static ref SPEED_FACTOR: Mutex = Mutex::new(1.0); - pub static ref INSTANT_PRINT_LINES: Mutex = Mutex::new(0); + pub static ref INSTANT_PRINT_LINES: Mutex = Mutex::new(0); pub static ref STARTED_AT: Instant = Instant::now(); pub static ref MODULES_RAN: AtomicU32 = AtomicU32::new(0); } From b1f10038832ac7026f21f18b457588eed6cf80d7 Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Fri, 8 Dec 2023 14:31:40 -0500 Subject: [PATCH 3/6] Trying to switch from mutex to u32 --- src/args.rs | 8 +------- src/io.rs | 4 ++-- src/lib.rs | 2 +- src/main.rs | 3 +-- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/args.rs b/src/args.rs index 5092b3e7e..64715d66c 100644 --- a/src/args.rs +++ b/src/args.rs @@ -12,12 +12,6 @@ fn parse_speed_factor(s: &str) -> Result { Ok(value_as_float) } -#[cfg(not(target_arch = "wasm32"))] -fn parse_instant_print(s: &str) -> Result { - let value_as_int = s.parse::().map_err(|e| e.to_string())?; - Ok(value_as_int) -} - #[cfg(not(target_arch = "wasm32"))] fn parse_min_1(s: &str) -> Result { let value_as_u32 = s.parse::().map_err(|e| e.to_string())?; @@ -44,7 +38,7 @@ pub struct AppConfig { pub speed_factor: f32, /// Instantly print this many lines - #[clap(short, long = "instant-print-lines", default_value = "0", value_parser = parse_instant_print)] + #[clap(short, long = "instant-print-lines", default_value = "0")] pub instant_print_lines: u32, /// Exit after running for this long (format example: 2h10min) diff --git a/src/io.rs b/src/io.rs index 07d54a5c5..bbf41080a 100644 --- a/src/io.rs +++ b/src/io.rs @@ -16,8 +16,8 @@ pub async fn csleep(length: u64) { use std::time; let speed_factor = *SPEED_FACTOR.lock().await; - let count = COUNTER.fetch_add(1, Ordering::Relaxed); - let sleep_length = if count < *INSTANT_PRINT_LINES.lock().await { + let count = COUNTER.fetch_add(1, Ordering::SeqCst); + let sleep_length = if count < INSTANT_PRINT_LINES.load(Ordering::SeqCst) { // If user passed `--instant-print-lines`, there should be // no pauses in first `INSTANT_PRINT_LINES` number of lines time::Duration::new(0, 0) diff --git a/src/lib.rs b/src/lib.rs index 9510fcddd..52f5a5a21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ use modules::{Module, ALL_MODULES}; lazy_static::lazy_static! { pub static ref CTRLC_PRESSED: AtomicBool = AtomicBool::new(false); pub static ref SPEED_FACTOR: Mutex = Mutex::new(1.0); - pub static ref INSTANT_PRINT_LINES: Mutex = Mutex::new(0); + pub static ref INSTANT_PRINT_LINES: AtomicU32 = AtomicU32::new(0); pub static ref STARTED_AT: Instant = Instant::now(); pub static ref MODULES_RAN: AtomicU32 = AtomicU32::new(0); } diff --git a/src/main.rs b/src/main.rs index 2b93dde5d..1caa252b2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::Result; use genact::args::parse_args; -use genact::{run, SPEED_FACTOR, INSTANT_PRINT_LINES}; +use genact::{run, SPEED_FACTOR}; #[cfg(not(target_arch = "wasm32"))] use genact::exit_handler; @@ -32,7 +32,6 @@ async fn main() -> Result<()> { } *SPEED_FACTOR.lock().await = appconfig.speed_factor; - *INSTANT_PRINT_LINES.lock().await = appconfig.instant_print_lines; if appconfig.list_modules_and_exit { println!("Available modules:"); From dd5e129fcdeaf6f9fcd04cb81aa0bfb92c24a2b8 Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Fri, 8 Dec 2023 15:31:59 -0500 Subject: [PATCH 4/6] Fix to switching from mutex to u32 --- src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1caa252b2..3438d73f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,9 @@ use anyhow::Result; use genact::args::parse_args; -use genact::{run, SPEED_FACTOR}; +use genact::{run, SPEED_FACTOR, INSTANT_PRINT_LINES}; + +use std::sync::atomic::Ordering; #[cfg(not(target_arch = "wasm32"))] use genact::exit_handler; @@ -32,6 +34,8 @@ async fn main() -> Result<()> { } *SPEED_FACTOR.lock().await = appconfig.speed_factor; + INSTANT_PRINT_LINES.store(appconfig.instant_print_lines, Ordering::SeqCst); + if appconfig.list_modules_and_exit { println!("Available modules:"); From 21e5b815bcfa4726681df91e9252a22e07c01dd5 Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Fri, 8 Dec 2023 15:41:32 -0500 Subject: [PATCH 5/6] Formatting adjustments --- src/io.rs | 2 +- src/main.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/io.rs b/src/io.rs index bbf41080a..3f2b62b13 100644 --- a/src/io.rs +++ b/src/io.rs @@ -6,7 +6,7 @@ use wasm_bindgen::prelude::*; #[cfg(not(target_arch = "wasm32"))] use std::io::{stdout, Write}; -use crate::{SPEED_FACTOR, INSTANT_PRINT_LINES}; +use crate::{INSTANT_PRINT_LINES, SPEED_FACTOR}; use std::sync::atomic::{AtomicU32, Ordering}; static COUNTER: AtomicU32 = AtomicU32::new(0); diff --git a/src/main.rs b/src/main.rs index 3438d73f0..9d59dd834 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use anyhow::Result; use genact::args::parse_args; -use genact::{run, SPEED_FACTOR, INSTANT_PRINT_LINES}; +use genact::{run, INSTANT_PRINT_LINES, SPEED_FACTOR}; use std::sync::atomic::Ordering; @@ -36,7 +36,6 @@ async fn main() -> Result<()> { *SPEED_FACTOR.lock().await = appconfig.speed_factor; INSTANT_PRINT_LINES.store(appconfig.instant_print_lines, Ordering::SeqCst); - if appconfig.list_modules_and_exit { println!("Available modules:"); for module in genact::modules::ALL_MODULES.keys() { From 24f4dd9878ce1321df53b4329c95c756cc3caf40 Mon Sep 17 00:00:00 2001 From: Josh Errickson Date: Sat, 9 Dec 2023 06:12:35 -0500 Subject: [PATCH 6/6] Added instant-print-lines support to wasm32 --- src/args.rs | 9 +++++++++ src/io.rs | 9 ++++++++- src/main.rs | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/args.rs b/src/args.rs index 64715d66c..e145a58d1 100644 --- a/src/args.rs +++ b/src/args.rs @@ -65,6 +65,9 @@ pub struct AppConfig { /// Global speed factor pub speed_factor: f32, + + /// Instantly print this many lines + pub instant_print_lines: u32, } impl AppConfig { @@ -126,6 +129,11 @@ pub fn parse_args() -> AppConfig { .map(|(_, v)| v.parse::().unwrap_or(1.0)) .unwrap_or(1.0); + let instant_print_lines: u32 = pairs + .find(|&(ref k, _)| k == "instant-print-lines") + .map(|(_, v)| v.parse::().unwrap_or(0)) + .unwrap_or(0); + let modules_to_run = if temp_modules.is_empty() { ALL_MODULES.keys().map(|m| m.to_string()).collect() } else { @@ -135,5 +143,6 @@ pub fn parse_args() -> AppConfig { AppConfig { modules: modules_to_run, speed_factor, + instant_print_lines, } } diff --git a/src/io.rs b/src/io.rs index 3f2b62b13..9741c59cc 100644 --- a/src/io.rs +++ b/src/io.rs @@ -30,7 +30,14 @@ pub async fn csleep(length: u64) { #[cfg(target_arch = "wasm32")] pub async fn csleep(length: u64) { let speed_factor = *SPEED_FACTOR.lock().await; - let sleep_length = (1.0 / speed_factor * length as f32) as i32; + let count = COUNTER.fetch_add(1, Ordering::SeqCst); + let sleep_length = if count < INSTANT_PRINT_LINES.load(Ordering::SeqCst) { + // If user passed `--instant-print-lines`, there should be + // no pauses in first `INSTANT_PRINT_LINES` number of lines + 0 as i32 + } else { + (1.0 / speed_factor * length as f32) as i32 + }; let promise = js_sys::Promise::new(&mut move |resolve, _| { let window = web_sys::window().expect("should have a Window"); diff --git a/src/main.rs b/src/main.rs index 9d59dd834..6ca26728e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,6 +60,7 @@ async fn main() { let appconfig = parse_args(); *SPEED_FACTOR.lock().await = appconfig.speed_factor; + INSTANT_PRINT_LINES.store(appconfig.instant_print_lines, Ordering::SeqCst); run(appconfig).await; }