Wrap Arc<AtomicUsize> around NewType Counter

And offers a simpler API
This commit is contained in:
Alexandre Bury 2016-07-26 23:29:13 -07:00
parent 8290c3f62a
commit bea7240271
2 changed files with 37 additions and 7 deletions

View File

@ -94,7 +94,7 @@ pub use self::menubar::Menubar;
pub use self::menu_popup::MenuPopup; pub use self::menu_popup::MenuPopup;
pub use self::view_path::ViewPath; pub use self::view_path::ViewPath;
pub use self::panel::Panel; 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::select_view::SelectView;
pub use self::shadow_view::ShadowView; pub use self::shadow_view::ShadowView;
pub use self::sized_view::SizedView; pub use self::sized_view::SizedView;

View File

@ -11,6 +11,32 @@ use view::View;
pub type CbPromise = Option<Box<Fn(&mut Cursive) + Send>>; pub type CbPromise = Option<Box<Fn(&mut Cursive) + Send>>;
/// Atomic counter used by `ProgressBar`.
#[derive(Clone)]
pub struct Counter(pub Arc<AtomicUsize>);
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. /// Animated bar showing a progress value.
/// ///
/// This bar has an internal counter, and adapts the length of the displayed /// This bar has an internal counter, and adapts the length of the displayed
@ -37,13 +63,17 @@ pub type CbPromise = Option<Box<Fn(&mut Cursive) + Send>>;
pub struct ProgressBar { pub struct ProgressBar {
min: usize, min: usize,
max: usize, max: usize,
value: Arc<AtomicUsize>, value: Counter,
// TODO: use a Promise instead? // TODO: use a Promise instead?
label_maker: Box<Fn(usize, (usize, usize)) -> String>, label_maker: Box<Fn(usize, (usize, usize)) -> 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(usize) + Send>; pub type Ticker = Box<Fn(usize) + Send>;
fn make_percentage(value: usize, (min, max): (usize, usize)) -> String { fn make_percentage(value: usize, (min, max): (usize, usize)) -> String {
if value < min { if value < min {
// ?? Negative progress? // ?? Negative progress?
@ -69,7 +99,7 @@ impl ProgressBar {
ProgressBar { ProgressBar {
min: 0, min: 0,
max: 100, max: 100,
value: Arc::new(AtomicUsize::new(0)), value: Counter::new(0),
label_maker: Box::new(make_percentage), label_maker: Box::new(make_percentage),
} }
} }
@ -78,7 +108,7 @@ impl ProgressBar {
/// ///
/// Use this to manually control the progress to display /// Use this to manually control the progress to display
/// by directly modifying the value pointed to by `value`. /// by directly modifying the value pointed to by `value`.
pub fn with_value(mut self, value: Arc<AtomicUsize>) -> Self { pub fn with_value(mut self, value: Counter) -> Self {
self.value = value; self.value = value;
self self
} }
@ -92,7 +122,7 @@ impl ProgressBar {
pub fn start<F: FnOnce(Ticker) + Send + 'static>(&mut self, f: F) { pub fn start<F: FnOnce(Ticker) + Send + 'static>(&mut self, f: F) {
let value = self.value.clone(); let value = self.value.clone();
let ticker: Ticker = Box::new(move |ticks| { let ticker: Ticker = Box::new(move |ticks| {
value.fetch_add(ticks, Ordering::Relaxed); value.tick(ticks);
}); });
thread::spawn(move || { thread::spawn(move || {
@ -168,7 +198,7 @@ impl ProgressBar {
/// ///
/// Value is clamped between `min` and `max`. /// Value is clamped between `min` and `max`.
pub fn set_value(&mut self, value: usize) { 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... // Now, the bar itself...
let available = printer.size.x; 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 under the minimum, don't draw anything.
// If we're over the maximum, we'll try to draw more, but the printer // If we're over the maximum, we'll try to draw more, but the printer