From bea7240271ad56cdada4a270a4d8d4b24ba5d2d9 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Tue, 26 Jul 2016 23:29:13 -0700 Subject: [PATCH] Wrap `Arc` around NewType `Counter` And offers a simpler API --- src/view/mod.rs | 2 +- src/view/progress_bar.rs | 42 ++++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/view/mod.rs b/src/view/mod.rs index a4c6818..f050c1a 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -94,7 +94,7 @@ pub use self::menubar::Menubar; pub use self::menu_popup::MenuPopup; pub use self::view_path::ViewPath; pub use self::panel::Panel; -pub use self::progress_bar::ProgressBar; +pub use self::progress_bar::{Counter, ProgressBar, Ticker}; pub use self::select_view::SelectView; pub use self::shadow_view::ShadowView; pub use self::sized_view::SizedView; diff --git a/src/view/progress_bar.rs b/src/view/progress_bar.rs index af0b4c0..c814df9 100644 --- a/src/view/progress_bar.rs +++ b/src/view/progress_bar.rs @@ -11,6 +11,32 @@ use view::View; pub type CbPromise = Option>; +/// Atomic counter used by `ProgressBar`. +#[derive(Clone)] +pub struct Counter(pub Arc); + +impl Counter { + /// Creates a new `Counter` starting with the given value. + pub fn new(value: usize) -> Self { + Counter(Arc::new(AtomicUsize::new(value))) + } + + /// Retrieves the current progress value. + pub fn get(&self) -> usize { + self.0.load(Ordering::Relaxed) + } + + /// Sets the current progress value. + pub fn set(&self, value: usize) { + self.0.store(value, Ordering::Relaxed); + } + + /// Increase the current progress by `ticks`. + pub fn tick(&self, ticks: usize) { + self.0.fetch_add(ticks, Ordering::Relaxed); + } +} + /// Animated bar showing a progress value. /// /// This bar has an internal counter, and adapts the length of the displayed @@ -37,13 +63,17 @@ pub type CbPromise = Option>; pub struct ProgressBar { min: usize, max: usize, - value: Arc, + value: Counter, // TODO: use a Promise instead? label_maker: Box String>, } +/// Function used by tasks given to a `ProgressBar`. +/// +/// This function will increment the progress bar counter by the given value. pub type Ticker = Box; + fn make_percentage(value: usize, (min, max): (usize, usize)) -> String { if value < min { // ?? Negative progress? @@ -69,7 +99,7 @@ impl ProgressBar { ProgressBar { min: 0, max: 100, - value: Arc::new(AtomicUsize::new(0)), + value: Counter::new(0), label_maker: Box::new(make_percentage), } } @@ -78,7 +108,7 @@ impl ProgressBar { /// /// Use this to manually control the progress to display /// by directly modifying the value pointed to by `value`. - pub fn with_value(mut self, value: Arc) -> Self { + pub fn with_value(mut self, value: Counter) -> Self { self.value = value; self } @@ -92,7 +122,7 @@ impl ProgressBar { pub fn start(&mut self, f: F) { let value = self.value.clone(); let ticker: Ticker = Box::new(move |ticks| { - value.fetch_add(ticks, Ordering::Relaxed); + value.tick(ticks); }); thread::spawn(move || { @@ -168,7 +198,7 @@ impl ProgressBar { /// /// Value is clamped between `min` and `max`. pub fn set_value(&mut self, value: usize) { - self.value.store(value, Ordering::Relaxed); + self.value.set(value); } } @@ -177,7 +207,7 @@ impl View for ProgressBar { // Now, the bar itself... let available = printer.size.x; - let value = self.value.load(Ordering::Relaxed); + let value = self.value.get(); // If we're under the minimum, don't draw anything. // If we're over the maximum, we'll try to draw more, but the printer