1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Merge pull request #935 from frewsxcv/refactor-time

Prefer handling `Duration` over `f32` when dealing with times.
This commit is contained in:
Nathan Ross 2016-08-04 21:17:38 -04:00 committed by GitHub
commit a8f5b430df
7 changed files with 25 additions and 30 deletions

1
Cargo.lock generated
View file

@ -1267,7 +1267,6 @@ name = "uucore"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View file

@ -61,19 +61,12 @@ specified by the sum of their values.", NAME, VERSION);
0 0
} }
fn float_to_duration(dur_f: f64) -> Duration {
let seconds = dur_f as u64;
let nanos = ((dur_f - seconds as f64) * 1e9) as u32;
Duration::new(seconds, nanos)
}
fn sleep(args: Vec<String>) { fn sleep(args: Vec<String>) {
let sleep_time = args.iter().fold(0.0, |result, arg| let sleep_dur = args.iter().fold(Duration::new(0, 0), |result, arg|
match uucore::parse_time::from_str(&arg[..]) { match uucore::parse_time::from_str(&arg[..]) {
Ok(m) => m + result, Ok(m) => m + result,
Err(f) => crash!(1, "{}", f), Err(f) => crash!(1, "{}", f),
}); });
let sleep_dur = float_to_duration(sleep_time);
thread::sleep(sleep_dur); thread::sleep(sleep_dur);
} }

View file

@ -18,6 +18,7 @@ extern crate uucore;
use std::io::{ErrorKind, Write}; use std::io::{ErrorKind, Write};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::time::Duration;
use uucore::process::ChildExt; use uucore::process::ChildExt;
static NAME: &'static str = "timeout"; static NAME: &'static str = "timeout";
@ -65,7 +66,7 @@ Usage:
return ERR_EXIT_STATUS; return ERR_EXIT_STATUS;
} }
}, },
None => 0f64 None => Duration::new(0, 0),
}; };
let signal = match matches.opt_str("signal") { let signal = match matches.opt_str("signal") {
Some(sigstr) => match uucore::signals::signal_by_name_or_value(&sigstr) { Some(sigstr) => match uucore::signals::signal_by_name_or_value(&sigstr) {
@ -90,7 +91,7 @@ Usage:
0 0
} }
fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_after: f64, foreground: bool, preserve_status: bool) -> i32 { fn timeout(cmdname: &str, args: &[String], duration: Duration, signal: usize, kill_after: Duration, foreground: bool, preserve_status: bool) -> i32 {
if !foreground { if !foreground {
unsafe { libc::setpgid(0, 0) }; unsafe { libc::setpgid(0, 0) };
} }
@ -124,7 +125,7 @@ fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_af
} }
}, },
Ok(None) => { Ok(None) => {
if kill_after == 0f64 { if kill_after == Duration::new(0, 0) {
// XXX: this may not be right // XXX: this may not be right
return 124; return 124;
} }

View file

@ -5,7 +5,6 @@ authors = []
[dependencies] [dependencies]
libc = "*" libc = "*"
time = "*"
winapi = "*" winapi = "*"
[lib] [lib]

View file

@ -1,5 +1,4 @@
extern crate libc; extern crate libc;
extern crate time;
#[cfg(windows)] extern crate winapi; #[cfg(windows)] extern crate winapi;
#[macro_use] #[macro_use]

View file

@ -7,7 +7,9 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
pub fn from_str(string: &str) -> Result<f64, String> { use std::time::Duration;
pub fn from_str(string: &str) -> Result<Duration, String> {
let len = string.len(); let len = string.len();
if len == 0 { if len == 0 {
return Err("empty string".to_owned()) return Err("empty string".to_owned())
@ -28,8 +30,14 @@ pub fn from_str(string: &str) -> Result<f64, String> {
} }
} }
}; };
match numstr.parse::<f64>() { let num = match numstr.parse::<f64>() {
Ok(m) => Ok(m * times as f64), Ok(m) => m,
Err(e) => Err(format!("invalid time interval '{}': {}", string, e)) Err(e) => return Err(format!("invalid time interval '{}': {}", string, e))
} };
const NANOS_PER_SEC: u32 = 1_000_000_000;
let whole_secs = num.trunc();
let nanos = (num.fract() * (NANOS_PER_SEC as f64)).trunc();
let duration = Duration::new(whole_secs as u64, nanos as u32);
Ok(duration * times)
} }

View file

@ -15,8 +15,7 @@ use std::io;
use std::process::Child; use std::process::Child;
use std::sync::{Arc, Condvar, Mutex}; use std::sync::{Arc, Condvar, Mutex};
use std::thread; use std::thread;
use time::{Duration, get_time}; use std::time::{Duration, Instant};
use std::time::Duration as StdDuration;
// This is basically sys::unix::process::ExitStatus // This is basically sys::unix::process::ExitStatus
#[derive(PartialEq, Eq, Clone, Copy, Debug)] #[derive(PartialEq, Eq, Clone, Copy, Debug)]
@ -71,7 +70,7 @@ pub trait ChildExt {
fn send_signal(&mut self, signal: usize) -> io::Result<()>; fn send_signal(&mut self, signal: usize) -> io::Result<()>;
/// Wait for a process to finish or return after the specified duration. /// Wait for a process to finish or return after the specified duration.
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>>; fn wait_or_timeout(&mut self, timeout: Duration) -> io::Result<Option<ExitStatus>>;
} }
impl ChildExt for Child { impl ChildExt for Child {
@ -84,7 +83,7 @@ impl ChildExt for Child {
} }
} }
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>> { fn wait_or_timeout(&mut self, timeout: Duration) -> io::Result<Option<ExitStatus>> {
// The result will be written to that Option, protected by a Mutex // The result will be written to that Option, protected by a Mutex
// Then the Condvar will be signaled // Then the Condvar will be signaled
let state = Arc::new(( let state = Arc::new((
@ -116,16 +115,13 @@ impl ChildExt for Child {
let &(ref lock, ref cvar) = &*state; let &(ref lock, ref cvar) = &*state;
let mut exitstatus = lock.lock().unwrap(); let mut exitstatus = lock.lock().unwrap();
// Condvar::wait_timeout_ms() can wake too soon, in this case wait again // Condvar::wait_timeout_ms() can wake too soon, in this case wait again
let target = get_time() + let start = Instant::now();
Duration::seconds(timeout as i64) +
Duration::nanoseconds((timeout * 1.0e-6) as i64);
while exitstatus.is_none() { while exitstatus.is_none() {
let now = get_time(); if start.elapsed() >= timeout {
if now >= target {
return Ok(None) return Ok(None)
} }
let ms = (target - get_time()).num_milliseconds() as u32; let cvar_timeout = timeout - start.elapsed();
exitstatus = cvar.wait_timeout(exitstatus, StdDuration::new(0, ms*1000)).unwrap().0; exitstatus = cvar.wait_timeout(exitstatus, cvar_timeout).unwrap().0;
} }
// Turn Option<Result<ExitStatus>> into Result<Option<ExitStatus>> // Turn Option<Result<ExitStatus>> into Result<Option<ExitStatus>>