Skip to content

Commit

Permalink
Rollup merge of rust-lang#56490 - faern:add-checked-add-to-instant, r…
Browse files Browse the repository at this point in the history
…=alexcrichton

Add checked_add method to Instant time type

Appending functionality to the already opened topic of `checked_add` on time types over at rust-lang#55940.

Doing checked addition between an `Instant` and a `Duration` is important to reliably determine a future instant. We could use this in the `parking_lot` crate to compute an instant when in the future to wake a thread up without risking a panic.
  • Loading branch information
kennytm authored Dec 12, 2018
2 parents a35ece4 + 442abbc commit 346d64d
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 161 deletions.
50 changes: 17 additions & 33 deletions src/libstd/sys/cloudabi/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,8 @@ pub struct Instant {

fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
dur.as_secs()
.checked_mul(NSEC_PER_SEC)
.and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
}

pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
checked_dur2intervals(dur)
.expect("overflow converting duration to nanoseconds")
.checked_mul(NSEC_PER_SEC)?
.checked_add(dur.subsec_nanos() as abi::timestamp)
}

impl Instant {
Expand All @@ -47,20 +42,16 @@ impl Instant {
Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant {
t: self.t
.checked_add(dur2intervals(other))
.expect("overflow when adding duration to instant"),
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant {
t: self.t.checked_add(checked_dur2intervals(other)?)?,
})
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant {
t: self.t
.checked_sub(dur2intervals(other))
.expect("overflow when subtracting duration from instant"),
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant {
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
})
}
}

Expand Down Expand Up @@ -95,23 +86,16 @@ impl SystemTime {
}
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
self.checked_add_duration(other)
.expect("overflow when adding duration to instant")
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
checked_dur2intervals(other)
.and_then(|d| self.t.checked_add(d))
.map(|t| SystemTime {t})
Some(SystemTime {
t: self.t.checked_add(checked_dur2intervals(other)?)?,
})
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime {
t: self.t
.checked_sub(dur2intervals(other))
.expect("overflow when subtracting duration from instant"),
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime {
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
})
}
}

Expand Down
34 changes: 12 additions & 22 deletions src/libstd/sys/redox/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ impl Timespec {
}
}

fn add_duration(&self, other: &Duration) -> Timespec {
self.checked_add_duration(other).expect("overflow when adding duration to time")
}

fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = other
.as_secs()
Expand All @@ -67,27 +63,25 @@ impl Timespec {
})
}

fn sub_duration(&self, other: &Duration) -> Timespec {
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = other
.as_secs()
.try_into() // <- target type would be `i64`
.ok()
.and_then(|secs| self.t.tv_sec.checked_sub(secs))
.expect("overflow when subtracting duration from time");
.and_then(|secs| self.t.tv_sec.checked_sub(secs))?;

// Similar to above, nanos can't overflow.
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
if nsec < 0 {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1).expect("overflow when subtracting \
duration from time");
secs = secs.checked_sub(1)?;
}
Timespec {
Some(Timespec {
t: syscall::TimeSpec {
tv_sec: secs,
tv_nsec: nsec as i32,
},
}
})
}
}

Expand Down Expand Up @@ -150,12 +144,12 @@ impl Instant {
})
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant { t: self.t.add_duration(other) }
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant { t: self.t.checked_add_duration(other)? })
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant { t: self.t.sub_duration(other) }
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant { t: self.t.checked_sub_duration(other)? })
}
}

Expand All @@ -178,16 +172,12 @@ impl SystemTime {
self.t.sub_timespec(&other.t)
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.add_duration(other) }
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.t.checked_add_duration(other).map(|t| SystemTime { t })
Some(SystemTime { t: self.t.checked_add_duration(other)? })
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.sub_duration(other) }
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
}
}

Expand Down
18 changes: 7 additions & 11 deletions src/libstd/sys/sgx/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ impl Instant {
self.0 - other.0
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant(self.0 + *other)
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_add(*other)?))
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant(self.0 - *other)
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_sub(*other)?))
}
}

Expand All @@ -47,15 +47,11 @@ impl SystemTime {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 + *other)
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.0.checked_add(*other).map(|d| SystemTime(d))
Some(SystemTime(self.0.checked_add(*other)?))
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 - *other)
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub(*other)?))
}
}
72 changes: 28 additions & 44 deletions src/libstd/sys/unix/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ impl Timespec {
}
}

fn add_duration(&self, other: &Duration) -> Timespec {
self.checked_add_duration(other).expect("overflow when adding duration to time")
}

fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = other
.as_secs()
Expand All @@ -68,27 +64,25 @@ impl Timespec {
})
}

fn sub_duration(&self, other: &Duration) -> Timespec {
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = other
.as_secs()
.try_into() // <- target type would be `libc::time_t`
.ok()
.and_then(|secs| self.t.tv_sec.checked_sub(secs))
.expect("overflow when subtracting duration from time");
.and_then(|secs| self.t.tv_sec.checked_sub(secs))?;

// Similar to above, nanos can't overflow.
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
if nsec < 0 {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1).expect("overflow when subtracting \
duration from time");
secs = secs.checked_sub(1)?;
}
Timespec {
Some(Timespec {
t: libc::timespec {
tv_sec: secs,
tv_nsec: nsec as _,
},
}
})
}
}

Expand Down Expand Up @@ -165,18 +159,16 @@ mod inner {
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant {
t: self.t.checked_add(dur2intervals(other))
.expect("overflow when adding duration to instant"),
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant {
t: self.t.checked_add(checked_dur2intervals(other)?)?,
})
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant {
t: self.t.checked_sub(dur2intervals(other))
.expect("overflow when subtracting duration from instant"),
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant {
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
})
}
}

Expand All @@ -199,16 +191,12 @@ mod inner {
self.t.sub_timespec(&other.t)
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.add_duration(other) }
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.t.checked_add_duration(other).map(|t| SystemTime { t })
Some(SystemTime { t: self.t.checked_add_duration(other)? })
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.sub_duration(other) }
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
}
}

Expand Down Expand Up @@ -236,12 +224,12 @@ mod inner {
}
}

fn dur2intervals(dur: &Duration) -> u64 {
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
let nanos = dur.as_secs()
.checked_mul(NSEC_PER_SEC)?
.checked_add(dur.subsec_nanos() as u64)?;
let info = info();
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
nanos.checked_add(dur.subsec_nanos() as u64)
}).expect("overflow converting duration to nanoseconds");
mul_div_u64(nanos, info.denom as u64, info.numer as u64)
Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
}

fn info() -> &'static libc::mach_timebase_info {
Expand Down Expand Up @@ -299,12 +287,12 @@ mod inner {
})
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant { t: self.t.add_duration(other) }
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant { t: self.t.checked_add_duration(other)? })
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant { t: self.t.sub_duration(other) }
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant { t: self.t.checked_sub_duration(other)? })
}
}

Expand All @@ -327,16 +315,12 @@ mod inner {
self.t.sub_timespec(&other.t)
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.add_duration(other) }
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.t.checked_add_duration(other).map(|t| SystemTime { t })
Some(SystemTime { t: self.t.checked_add_duration(other)? })
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime { t: self.t.sub_duration(other) }
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
}
}

Expand Down
18 changes: 7 additions & 11 deletions src/libstd/sys/wasm/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ impl Instant {
self.0 - other.0
}

pub fn add_duration(&self, other: &Duration) -> Instant {
Instant(self.0 + *other)
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_add(*other)?))
}

pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant(self.0 - *other)
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_sub(*other)?))
}
}

Expand All @@ -47,15 +47,11 @@ impl SystemTime {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}

pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 + *other)
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.0.checked_add(*other).map(|d| SystemTime(d))
Some(SystemTime(self.0.checked_add(*other)?))
}

pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 - *other)
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub(*other)?))
}
}
Loading

0 comments on commit 346d64d

Please sign in to comment.