diff --git a/crossbeam-channel/src/channel.rs b/crossbeam-channel/src/channel.rs index 8988235db..8bd4fe953 100644 --- a/crossbeam-channel/src/channel.rs +++ b/crossbeam-channel/src/channel.rs @@ -14,6 +14,7 @@ use crate::err::{ }; use crate::flavors; use crate::select::{Operation, SelectHandle, Token}; +use crate::utils; /// Creates a channel of unbounded capacity. /// @@ -471,7 +472,7 @@ impl Sender { /// ); /// ``` pub fn send_timeout(&self, msg: T, timeout: Duration) -> Result<(), SendTimeoutError> { - self.send_deadline(msg, Instant::now() + timeout) + self.send_deadline(msg, utils::convert_timeout_to_deadline(timeout)) } /// Waits for a message to be sent into the channel, but only until a given deadline. @@ -861,7 +862,7 @@ impl Receiver { /// ); /// ``` pub fn recv_timeout(&self, timeout: Duration) -> Result { - self.recv_deadline(Instant::now() + timeout) + self.recv_deadline(utils::convert_timeout_to_deadline(timeout)) } /// Waits for a message to be received from the channel, but only before a given deadline. diff --git a/crossbeam-channel/src/flavors/at.rs b/crossbeam-channel/src/flavors/at.rs index 23a7ae734..ca5ee60f5 100644 --- a/crossbeam-channel/src/flavors/at.rs +++ b/crossbeam-channel/src/flavors/at.rs @@ -35,7 +35,7 @@ impl Channel { /// Creates a channel that delivers a message after a certain duration of time. #[inline] pub(crate) fn new_timeout(dur: Duration) -> Self { - Self::new_deadline(Instant::now() + dur) + Self::new_deadline(utils::convert_timeout_to_deadline(dur)) } /// Attempts to receive a message without blocking. diff --git a/crossbeam-channel/src/flavors/tick.rs b/crossbeam-channel/src/flavors/tick.rs index bd12929a9..4201b6eb0 100644 --- a/crossbeam-channel/src/flavors/tick.rs +++ b/crossbeam-channel/src/flavors/tick.rs @@ -10,6 +10,7 @@ use crossbeam_utils::atomic::AtomicCell; use crate::context::Context; use crate::err::{RecvTimeoutError, TryRecvError}; use crate::select::{Operation, SelectHandle, Token}; +use crate::utils; /// Result of a receive operation. pub(crate) type TickToken = Option; @@ -28,7 +29,7 @@ impl Channel { #[inline] pub(crate) fn new(dur: Duration) -> Self { Channel { - delivery_time: AtomicCell::new(Instant::now() + dur), + delivery_time: AtomicCell::new(utils::convert_timeout_to_deadline(dur)), duration: dur, } } diff --git a/crossbeam-channel/src/select.rs b/crossbeam-channel/src/select.rs index ea70a9eb1..710b61221 100644 --- a/crossbeam-channel/src/select.rs +++ b/crossbeam-channel/src/select.rs @@ -487,7 +487,7 @@ pub fn select_timeout<'a>( handles: &mut [(&'a dyn SelectHandle, usize, *const u8)], timeout: Duration, ) -> Result, SelectTimeoutError> { - select_deadline(handles, Instant::now() + timeout) + select_deadline(handles, utils::convert_timeout_to_deadline(timeout)) } /// Blocks until a given deadline, or until one of the operations becomes ready and selects it. @@ -1043,7 +1043,7 @@ impl<'a> Select<'a> { /// } /// ``` pub fn ready_timeout(&mut self, timeout: Duration) -> Result { - self.ready_deadline(Instant::now() + timeout) + self.ready_deadline(utils::convert_timeout_to_deadline(timeout)) } /// Blocks until a given deadline, or until one of the operations becomes ready. diff --git a/crossbeam-channel/src/utils.rs b/crossbeam-channel/src/utils.rs index 557b6a0d7..d87c2408c 100644 --- a/crossbeam-channel/src/utils.rs +++ b/crossbeam-channel/src/utils.rs @@ -61,6 +61,14 @@ pub(crate) fn sleep_until(deadline: Option) { } } +// https://github.com/crossbeam-rs/crossbeam/issues/795 +pub(crate) fn convert_timeout_to_deadline(timeout: Duration) -> Instant { + match Instant::now().checked_add(timeout) { + Some(deadline) => deadline, + None => Instant::now() + Duration::from_secs(86400 * 365 * 30), + } +} + /// A simple spinlock. pub(crate) struct Spinlock { flag: AtomicBool,