//! Channel that delivers a message at a certain moment in time. //! //! Messages cannot be sent into this kind of channel; they are materialized on demand.
use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use std::time::Instant;
/// Result of a receive operation. pub(crate) type AtToken = Option<Instant>;
/// Channel that delivers a message at a certain moment in time pub(crate) struct Channel { /// The instant at which the message will be delivered.
delivery_time: Instant,
/// `true` if the message has been received.
received: AtomicBool,
}
impl Channel { /// Creates a channel that delivers a message at a certain instant in time. #[inline] pub(crate) fn new_deadline(when: Instant) -> Self {
Channel {
delivery_time: when,
received: AtomicBool::new(false),
}
}
/// Attempts to receive a message without blocking. #[inline] pub(crate) fn try_recv(&self) -> Result<Instant, TryRecvError> { // We use relaxed ordering because this is just an optional optimistic check. ifself.received.load(Ordering::Relaxed) { // The message has already been received. return Err(TryRecvError::Empty);
}
if Instant::now() < self.delivery_time { // The message was not delivered yet. return Err(TryRecvError::Empty);
}
// Try receiving the message if it is still available. if !self.received.swap(true, Ordering::SeqCst) { // Success! Return delivery time as the message.
Ok(self.delivery_time)
} else { // The message was already received.
Err(TryRecvError::Empty)
}
}
/// Receives a message from the channel. #[inline] pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> { // We use relaxed ordering because this is just an optional optimistic check. ifself.received.load(Ordering::Relaxed) { // The message has already been received.
utils::sleep_until(deadline); return Err(RecvTimeoutError::Timeout);
}
// Wait until the message is received or the deadline is reached. loop { let now = Instant::now();
let deadline = match deadline { // Check if we can receive the next message.
_ if now >= self.delivery_time => break, // Check if the timeout deadline has been reached.
Some(d) if now >= d => return Err(RecvTimeoutError::Timeout),
// Sleep until one of the above happens
Some(d) if d < self.delivery_time => d,
_ => self.delivery_time,
};
thread::sleep(deadline - now);
}
// Try receiving the message if it is still available. if !self.received.swap(true, Ordering::SeqCst) { // Success! Return the message, which is the instant at which it was delivered.
Ok(self.delivery_time)
} else { // The message was already received. Block forever.
utils::sleep_until(None);
unreachable!()
}
}
/// Reads a message from the channel. #[inline] pub(crate) unsafefn read(&self, token: &mut Token) -> Result<Instant, ()> {
token.at.ok_or(())
}
/// Returns `true` if the channel is empty. #[inline] pub(crate) fn is_empty(&self) -> bool { // We use relaxed ordering because this is just an optional optimistic check. ifself.received.load(Ordering::Relaxed) { returntrue;
}
// If the delivery time hasn't been reached yet, the channel is empty. if Instant::now() < self.delivery_time { returntrue;
}
// The delivery time has been reached. The channel is empty only if the message has already // been received. self.received.load(Ordering::SeqCst)
}
/// Returns `true` if the channel is full. #[inline] pub(crate) fn is_full(&self) -> bool {
!self.is_empty()
}
/// Returns the number of messages in the channel. #[inline] pub(crate) fn len(&self) -> usize { ifself.is_empty() { 0
} else { 1
}
}
/// Returns the capacity of the channel. #[inline] pub(crate) fn capacity(&self) -> Option<usize> {
Some(1)
}
}
#[inline] fn deadline(&self) -> Option<Instant> { // We use relaxed ordering because this is just an optional optimistic check. ifself.received.load(Ordering::Relaxed) {
None
} else {
Some(self.delivery_time)
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.