Skip to content

Commit f4b07e0

Browse files
committed
Auto merge of rust-lang#56490 - faern:add-checked-add-to-instant, r=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.
2 parents 664ede8 + 9e5e89a commit f4b07e0

File tree

9 files changed

+150
-166
lines changed

9 files changed

+150
-166
lines changed

src/libstd/sys/cloudabi/condvar.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use mem;
1313
use sync::atomic::{AtomicU32, Ordering};
1414
use sys::cloudabi::abi;
1515
use sys::mutex::{self, Mutex};
16-
use sys::time::dur2intervals;
16+
use sys::time::checked_dur2intervals;
1717
use time::Duration;
1818

1919
extern "C" {
@@ -114,6 +114,8 @@ impl Condvar {
114114

115115
// Call into the kernel to wait on the condition variable.
116116
let condvar = self.condvar.get();
117+
let timeout = checked_dur2intervals(&dur)
118+
.expect("overflow converting duration to nanoseconds");
117119
let subscriptions = [
118120
abi::subscription {
119121
type_: abi::eventtype::CONDVAR,
@@ -132,7 +134,7 @@ impl Condvar {
132134
union: abi::subscription_union {
133135
clock: abi::subscription_clock {
134136
clock_id: abi::clockid::MONOTONIC,
135-
timeout: dur2intervals(&dur),
137+
timeout,
136138
..mem::zeroed()
137139
},
138140
},

src/libstd/sys/cloudabi/thread.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use libc;
1616
use mem;
1717
use ptr;
1818
use sys::cloudabi::abi;
19-
use sys::time::dur2intervals;
19+
use sys::time::checked_dur2intervals;
2020
use sys_common::thread::*;
2121
use time::Duration;
2222

@@ -70,13 +70,15 @@ impl Thread {
7070
}
7171

7272
pub fn sleep(dur: Duration) {
73+
let timeout = checked_dur2intervals(&dur)
74+
.expect("overflow converting duration to nanoseconds");
7375
unsafe {
7476
let subscription = abi::subscription {
7577
type_: abi::eventtype::CLOCK,
7678
union: abi::subscription_union {
7779
clock: abi::subscription_clock {
7880
clock_id: abi::clockid::MONOTONIC,
79-
timeout: dur2intervals(&dur),
81+
timeout,
8082
..mem::zeroed()
8183
},
8284
},

src/libstd/sys/cloudabi/time.rs

+18-34
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,10 @@ pub struct Instant {
1919
t: abi::timestamp,
2020
}
2121

22-
fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
22+
pub fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
2323
dur.as_secs()
24-
.checked_mul(NSEC_PER_SEC)
25-
.and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
26-
}
27-
28-
pub fn dur2intervals(dur: &Duration) -> abi::timestamp {
29-
checked_dur2intervals(dur)
30-
.expect("overflow converting duration to nanoseconds")
24+
.checked_mul(NSEC_PER_SEC)?
25+
.checked_add(dur.subsec_nanos() as abi::timestamp)
3126
}
3227

3328
impl Instant {
@@ -47,20 +42,16 @@ impl Instant {
4742
Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
4843
}
4944

50-
pub fn add_duration(&self, other: &Duration) -> Instant {
51-
Instant {
52-
t: self.t
53-
.checked_add(dur2intervals(other))
54-
.expect("overflow when adding duration to instant"),
55-
}
45+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
46+
Some(Instant {
47+
t: self.t.checked_add(checked_dur2intervals(other)?)?,
48+
})
5649
}
5750

58-
pub fn sub_duration(&self, other: &Duration) -> Instant {
59-
Instant {
60-
t: self.t
61-
.checked_sub(dur2intervals(other))
62-
.expect("overflow when subtracting duration from instant"),
63-
}
51+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
52+
Some(Instant {
53+
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
54+
})
6455
}
6556
}
6657

@@ -95,23 +86,16 @@ impl SystemTime {
9586
}
9687
}
9788

98-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
99-
self.checked_add_duration(other)
100-
.expect("overflow when adding duration to instant")
101-
}
102-
10389
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
104-
checked_dur2intervals(other)
105-
.and_then(|d| self.t.checked_add(d))
106-
.map(|t| SystemTime {t})
90+
Some(SystemTime {
91+
t: self.t.checked_add(checked_dur2intervals(other)?)?,
92+
})
10793
}
10894

109-
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
110-
SystemTime {
111-
t: self.t
112-
.checked_sub(dur2intervals(other))
113-
.expect("overflow when subtracting duration from instant"),
114-
}
95+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
96+
Some(SystemTime {
97+
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
98+
})
11599
}
116100
}
117101

src/libstd/sys/redox/time.rs

+12-22
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ impl Timespec {
4141
}
4242
}
4343

44-
fn add_duration(&self, other: &Duration) -> Timespec {
45-
self.checked_add_duration(other).expect("overflow when adding duration to time")
46-
}
47-
4844
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
4945
let mut secs = other
5046
.as_secs()
@@ -67,27 +63,25 @@ impl Timespec {
6763
})
6864
}
6965

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

7873
// Similar to above, nanos can't overflow.
7974
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
8075
if nsec < 0 {
8176
nsec += NSEC_PER_SEC as i32;
82-
secs = secs.checked_sub(1).expect("overflow when subtracting \
83-
duration from time");
77+
secs = secs.checked_sub(1)?;
8478
}
85-
Timespec {
79+
Some(Timespec {
8680
t: syscall::TimeSpec {
8781
tv_sec: secs,
8882
tv_nsec: nsec as i32,
8983
},
90-
}
84+
})
9185
}
9286
}
9387

@@ -150,12 +144,12 @@ impl Instant {
150144
})
151145
}
152146

153-
pub fn add_duration(&self, other: &Duration) -> Instant {
154-
Instant { t: self.t.add_duration(other) }
147+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
148+
Some(Instant { t: self.t.checked_add_duration(other)? })
155149
}
156150

157-
pub fn sub_duration(&self, other: &Duration) -> Instant {
158-
Instant { t: self.t.sub_duration(other) }
151+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
152+
Some(Instant { t: self.t.checked_sub_duration(other)? })
159153
}
160154
}
161155

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

181-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
182-
SystemTime { t: self.t.add_duration(other) }
183-
}
184-
185175
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
186-
self.t.checked_add_duration(other).map(|t| SystemTime { t })
176+
Some(SystemTime { t: self.t.checked_add_duration(other)? })
187177
}
188178

189-
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
190-
SystemTime { t: self.t.sub_duration(other) }
179+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
180+
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
191181
}
192182
}
193183

src/libstd/sys/sgx/time.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ impl Instant {
2828
self.0 - other.0
2929
}
3030

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

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

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

50-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
51-
SystemTime(self.0 + *other)
52-
}
53-
5450
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
55-
self.0.checked_add(*other).map(|d| SystemTime(d))
51+
Some(SystemTime(self.0.checked_add(*other)?))
5652
}
5753

58-
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
59-
SystemTime(self.0 - *other)
54+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
55+
Some(SystemTime(self.0.checked_sub(*other)?))
6056
}
6157
}

src/libstd/sys/unix/time.rs

+28-44
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ impl Timespec {
4242
}
4343
}
4444

45-
fn add_duration(&self, other: &Duration) -> Timespec {
46-
self.checked_add_duration(other).expect("overflow when adding duration to time")
47-
}
48-
4945
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
5046
let mut secs = other
5147
.as_secs()
@@ -68,27 +64,25 @@ impl Timespec {
6864
})
6965
}
7066

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

7974
// Similar to above, nanos can't overflow.
8075
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
8176
if nsec < 0 {
8277
nsec += NSEC_PER_SEC as i32;
83-
secs = secs.checked_sub(1).expect("overflow when subtracting \
84-
duration from time");
78+
secs = secs.checked_sub(1)?;
8579
}
86-
Timespec {
80+
Some(Timespec {
8781
t: libc::timespec {
8882
tv_sec: secs,
8983
tv_nsec: nsec as _,
9084
},
91-
}
85+
})
9286
}
9387
}
9488

@@ -165,18 +159,16 @@ mod inner {
165159
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
166160
}
167161

168-
pub fn add_duration(&self, other: &Duration) -> Instant {
169-
Instant {
170-
t: self.t.checked_add(dur2intervals(other))
171-
.expect("overflow when adding duration to instant"),
172-
}
162+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
163+
Some(Instant {
164+
t: self.t.checked_add(checked_dur2intervals(other)?)?,
165+
})
173166
}
174167

175-
pub fn sub_duration(&self, other: &Duration) -> Instant {
176-
Instant {
177-
t: self.t.checked_sub(dur2intervals(other))
178-
.expect("overflow when subtracting duration from instant"),
179-
}
168+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
169+
Some(Instant {
170+
t: self.t.checked_sub(checked_dur2intervals(other)?)?,
171+
})
180172
}
181173
}
182174

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

202-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
203-
SystemTime { t: self.t.add_duration(other) }
204-
}
205-
206194
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
207-
self.t.checked_add_duration(other).map(|t| SystemTime { t })
195+
Some(SystemTime { t: self.t.checked_add_duration(other)? })
208196
}
209197

210-
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
211-
SystemTime { t: self.t.sub_duration(other) }
198+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
199+
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
212200
}
213201
}
214202

@@ -236,12 +224,12 @@ mod inner {
236224
}
237225
}
238226

239-
fn dur2intervals(dur: &Duration) -> u64 {
227+
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
228+
let nanos = dur.as_secs()
229+
.checked_mul(NSEC_PER_SEC)?
230+
.checked_add(dur.subsec_nanos() as u64)?;
240231
let info = info();
241-
let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
242-
nanos.checked_add(dur.subsec_nanos() as u64)
243-
}).expect("overflow converting duration to nanoseconds");
244-
mul_div_u64(nanos, info.denom as u64, info.numer as u64)
232+
Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
245233
}
246234

247235
fn info() -> &'static libc::mach_timebase_info {
@@ -299,12 +287,12 @@ mod inner {
299287
})
300288
}
301289

302-
pub fn add_duration(&self, other: &Duration) -> Instant {
303-
Instant { t: self.t.add_duration(other) }
290+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
291+
Some(Instant { t: self.t.checked_add_duration(other)? })
304292
}
305293

306-
pub fn sub_duration(&self, other: &Duration) -> Instant {
307-
Instant { t: self.t.sub_duration(other) }
294+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
295+
Some(Instant { t: self.t.checked_sub_duration(other)? })
308296
}
309297
}
310298

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

330-
pub fn add_duration(&self, other: &Duration) -> SystemTime {
331-
SystemTime { t: self.t.add_duration(other) }
332-
}
333-
334318
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
335-
self.t.checked_add_duration(other).map(|t| SystemTime { t })
319+
Some(SystemTime { t: self.t.checked_add_duration(other)? })
336320
}
337321

338-
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
339-
SystemTime { t: self.t.sub_duration(other) }
322+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
323+
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
340324
}
341325
}
342326

0 commit comments

Comments
 (0)