diff options
Diffstat (limited to 'third_party/rust/mio/src/sys/unix/ready.rs')
-rw-r--r-- | third_party/rust/mio/src/sys/unix/ready.rs | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/third_party/rust/mio/src/sys/unix/ready.rs b/third_party/rust/mio/src/sys/unix/ready.rs new file mode 100644 index 0000000000..1780ceae9f --- /dev/null +++ b/third_party/rust/mio/src/sys/unix/ready.rs @@ -0,0 +1,499 @@ +use event_imp::{Ready, ready_as_usize, ready_from_usize}; + +use std::ops; +use std::fmt; + +/// Unix specific extensions to `Ready` +/// +/// Provides additional readiness event kinds that are available on unix +/// platforms. Unix platforms are able to provide readiness events for +/// additional socket events, such as HUP and error. +/// +/// HUP events occur when the remote end of a socket hangs up. In the TCP case, +/// this occurs when the remote end of a TCP socket shuts down writes. +/// +/// Error events occur when the socket enters an error state. In this case, the +/// socket will also receive a readable or writable event. Reading or writing to +/// the socket will result in an error. +/// +/// Conversion traits are implemented between `Ready` and `UnixReady`. See the +/// examples. +/// +/// For high level documentation on polling and readiness, see [`Poll`]. +/// +/// # Examples +/// +/// Most of the time, all that is needed is using bit operations +/// +/// ``` +/// use mio::Ready; +/// use mio::unix::UnixReady; +/// +/// let ready = Ready::readable() | UnixReady::hup(); +/// +/// assert!(ready.is_readable()); +/// assert!(UnixReady::from(ready).is_hup()); +/// ``` +/// +/// Basic conversion between ready types. +/// +/// ``` +/// use mio::Ready; +/// use mio::unix::UnixReady; +/// +/// // Start with a portable ready +/// let ready = Ready::readable(); +/// +/// // Convert to a unix ready, adding HUP +/// let mut unix_ready = UnixReady::from(ready) | UnixReady::hup(); +/// +/// unix_ready.insert(UnixReady::error()); +/// +/// // `unix_ready` maintains readable interest +/// assert!(unix_ready.is_readable()); +/// assert!(unix_ready.is_hup()); +/// assert!(unix_ready.is_error()); +/// +/// // Convert back to `Ready` +/// let ready = Ready::from(unix_ready); +/// +/// // Readable is maintained +/// assert!(ready.is_readable()); +/// ``` +/// +/// Registering readable and error interest on a socket +/// +/// ``` +/// # use std::error::Error; +/// # fn try_main() -> Result<(), Box<Error>> { +/// use mio::{Ready, Poll, PollOpt, Token}; +/// use mio::net::TcpStream; +/// use mio::unix::UnixReady; +/// +/// let addr = "216.58.193.68:80".parse()?; +/// let socket = TcpStream::connect(&addr)?; +/// +/// let poll = Poll::new()?; +/// +/// poll.register(&socket, +/// Token(0), +/// Ready::readable() | UnixReady::error(), +/// PollOpt::edge())?; +/// # Ok(()) +/// # } +/// # +/// # fn main() { +/// # try_main().unwrap(); +/// # } +/// ``` +/// +/// [`Poll`]: ../struct.Poll.html +/// [readiness]: struct.Poll.html#readiness-operations +#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)] +pub struct UnixReady(Ready); + +const ERROR: usize = 0b00_0100; +const HUP: usize = 0b00_1000; + +#[cfg(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos"))] +const AIO: usize = 0b01_0000; + +#[cfg(not(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos")))] +const AIO: usize = 0b00_0000; + +#[cfg(any(target_os = "freebsd"))] +const LIO: usize = 0b10_0000; + +#[cfg(not(any(target_os = "freebsd")))] +const LIO: usize = 0b00_0000; + +#[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))] +const PRI: usize = 0b100_0000; + +#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "solaris")))] +const PRI: usize = 0; + +// Export to support `Ready::all` +pub const READY_ALL: usize = ERROR | HUP | AIO | LIO | PRI; + +#[test] +fn test_ready_all() { + let readable = Ready::readable().as_usize(); + let writable = Ready::writable().as_usize(); + + assert_eq!( + READY_ALL | readable | writable, + ERROR + HUP + AIO + LIO + PRI + readable + writable + ); + + // Issue #896. + #[cfg(any(target_os = "linux", target_os = "android", target_os = "solaris"))] + assert!(!Ready::from(UnixReady::priority()).is_writable()); +} + +impl UnixReady { + /// Returns a `Ready` representing AIO completion readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::aio(); + /// + /// assert!(ready.is_aio()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + #[inline] + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos"))] + pub fn aio() -> UnixReady { + UnixReady(ready_from_usize(AIO)) + } + + #[cfg(not(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos")))] + #[deprecated(since = "0.6.12", note = "this function is now platform specific")] + #[doc(hidden)] + pub fn aio() -> UnixReady { + UnixReady(Ready::empty()) + } + + /// Returns a `Ready` representing error readiness. + /// + /// **Note that only readable and writable readiness is guaranteed to be + /// supported on all platforms**. This means that `error` readiness + /// should be treated as a hint. For more details, see [readiness] in the + /// poll documentation. + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::error(); + /// + /// assert!(ready.is_error()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + /// [readiness]: ../struct.Poll.html#readiness-operations + #[inline] + pub fn error() -> UnixReady { + UnixReady(ready_from_usize(ERROR)) + } + + /// Returns a `Ready` representing HUP readiness. + /// + /// A HUP (or hang-up) signifies that a stream socket **peer** closed the + /// connection, or shut down the writing half of the connection. + /// + /// **Note that only readable and writable readiness is guaranteed to be + /// supported on all platforms**. This means that `hup` readiness + /// should be treated as a hint. For more details, see [readiness] in the + /// poll documentation. It is also unclear if HUP readiness will remain in 0.7. See + /// [here][issue-941]. + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::hup(); + /// + /// assert!(ready.is_hup()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + /// [readiness]: ../struct.Poll.html#readiness-operations + /// [issue-941]: https://github.com/tokio-rs/mio/issues/941 + #[inline] + pub fn hup() -> UnixReady { + UnixReady(ready_from_usize(HUP)) + } + + /// Returns a `Ready` representing LIO completion readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::lio(); + /// + /// assert!(ready.is_lio()); + /// ``` + /// + /// [`Poll`]: struct.Poll.html + #[inline] + #[cfg(any(target_os = "freebsd"))] + pub fn lio() -> UnixReady { + UnixReady(ready_from_usize(LIO)) + } + + /// Returns a `Ready` representing priority (`EPOLLPRI`) readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::priority(); + /// + /// assert!(ready.is_priority()); + /// ``` + /// + /// [`Poll`]: struct.Poll.html + #[inline] + #[cfg(any(target_os = "linux", + target_os = "android", target_os = "solaris"))] + pub fn priority() -> UnixReady { + UnixReady(ready_from_usize(PRI)) + } + + /// Returns true if `Ready` contains AIO readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::aio(); + /// + /// assert!(ready.is_aio()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + #[inline] + #[cfg(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos"))] + pub fn is_aio(&self) -> bool { + self.contains(ready_from_usize(AIO)) + } + + #[deprecated(since = "0.6.12", note = "this function is now platform specific")] + #[cfg(feature = "with-deprecated")] + #[cfg(not(any(target_os = "dragonfly", + target_os = "freebsd", target_os = "ios", target_os = "macos")))] + #[doc(hidden)] + pub fn is_aio(&self) -> bool { + false + } + + /// Returns true if the value includes error readiness + /// + /// **Note that only readable and writable readiness is guaranteed to be + /// supported on all platforms**. This means that `error` readiness should + /// be treated as a hint. For more details, see [readiness] in the poll + /// documentation. + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::error(); + /// + /// assert!(ready.is_error()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + /// [readiness]: ../struct.Poll.html#readiness-operations + #[inline] + pub fn is_error(&self) -> bool { + self.contains(ready_from_usize(ERROR)) + } + + /// Returns true if the value includes HUP readiness + /// + /// A HUP (or hang-up) signifies that a stream socket **peer** closed the + /// connection, or shut down the writing half of the connection. + /// + /// **Note that only readable and writable readiness is guaranteed to be + /// supported on all platforms**. This means that `hup` readiness + /// should be treated as a hint. For more details, see [readiness] in the + /// poll documentation. + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::hup(); + /// + /// assert!(ready.is_hup()); + /// ``` + /// + /// [`Poll`]: ../struct.Poll.html + /// [readiness]: ../struct.Poll.html#readiness-operations + #[inline] + pub fn is_hup(&self) -> bool { + self.contains(ready_from_usize(HUP)) + } + + /// Returns true if `Ready` contains LIO readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::lio(); + /// + /// assert!(ready.is_lio()); + /// ``` + #[inline] + #[cfg(any(target_os = "freebsd"))] + pub fn is_lio(&self) -> bool { + self.contains(ready_from_usize(LIO)) + } + + /// Returns true if `Ready` contains priority (`EPOLLPRI`) readiness + /// + /// See [`Poll`] for more documentation on polling. + /// + /// # Examples + /// + /// ``` + /// use mio::unix::UnixReady; + /// + /// let ready = UnixReady::priority(); + /// + /// assert!(ready.is_priority()); + /// ``` + /// + /// [`Poll`]: struct.Poll.html + #[inline] + #[cfg(any(target_os = "linux", + target_os = "android", target_os = "solaris"))] + pub fn is_priority(&self) -> bool { + self.contains(ready_from_usize(PRI)) + } +} + +impl From<Ready> for UnixReady { + fn from(src: Ready) -> UnixReady { + UnixReady(src) + } +} + +impl From<UnixReady> for Ready { + fn from(src: UnixReady) -> Ready { + src.0 + } +} + +impl ops::Deref for UnixReady { + type Target = Ready; + + fn deref(&self) -> &Ready { + &self.0 + } +} + +impl ops::DerefMut for UnixReady { + fn deref_mut(&mut self) -> &mut Ready { + &mut self.0 + } +} + +impl ops::BitOr for UnixReady { + type Output = UnixReady; + + #[inline] + fn bitor(self, other: UnixReady) -> UnixReady { + (self.0 | other.0).into() + } +} + +impl ops::BitXor for UnixReady { + type Output = UnixReady; + + #[inline] + fn bitxor(self, other: UnixReady) -> UnixReady { + (self.0 ^ other.0).into() + } +} + +impl ops::BitAnd for UnixReady { + type Output = UnixReady; + + #[inline] + fn bitand(self, other: UnixReady) -> UnixReady { + (self.0 & other.0).into() + } +} + +impl ops::Sub for UnixReady { + type Output = UnixReady; + + #[inline] + fn sub(self, other: UnixReady) -> UnixReady { + ready_from_usize(ready_as_usize(self.0) & !ready_as_usize(other.0)).into() + } +} + +#[deprecated(since = "0.6.10", note = "removed")] +#[cfg(feature = "with-deprecated")] +#[doc(hidden)] +impl ops::Not for UnixReady { + type Output = UnixReady; + + #[inline] + fn not(self) -> UnixReady { + (!self.0).into() + } +} + +impl fmt::Debug for UnixReady { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut one = false; + let flags = [ + (UnixReady(Ready::readable()), "Readable"), + (UnixReady(Ready::writable()), "Writable"), + (UnixReady::error(), "Error"), + (UnixReady::hup(), "Hup"), + #[allow(deprecated)] + (UnixReady::aio(), "Aio"), + #[cfg(any(target_os = "linux", + target_os = "android", target_os = "solaris"))] + (UnixReady::priority(), "Priority"), + ]; + + for &(flag, msg) in &flags { + if self.contains(flag) { + if one { write!(fmt, " | ")? } + write!(fmt, "{}", msg)?; + + one = true + } + } + + if !one { + fmt.write_str("(empty)")?; + } + + Ok(()) + } +} |