diff --git a/changelog/2631.removed.md b/changelog/2631.removed.md new file mode 100644 index 0000000000..3f75506895 --- /dev/null +++ b/changelog/2631.removed.md @@ -0,0 +1 @@ +Removed the `Copy` trait from `PollFd` diff --git a/src/poll.rs b/src/poll.rs index 9bbae5b3ba..416a6945ec 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -11,10 +11,10 @@ use crate::Result; /// [`ppoll`](fn.ppoll.html) functions to specify the events of interest /// for a specific file descriptor. /// -/// After a call to `poll` or `ppoll`, the events that occurred can be -/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. +/// After a call to `poll` or `ppoll`, the events that occurred can be retrieved by calling +/// [`revents()`](#method.revents) on the `PollFd` object from the array passed to `poll`. #[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PollFd<'fd> { pollfd: libc::pollfd, _fd: std::marker::PhantomData>, @@ -33,11 +33,8 @@ impl<'fd> PollFd<'fd> { /// # }; /// let (r, w) = pipe().unwrap(); /// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN); - /// let mut fds = [pfd]; - /// poll(&mut fds, PollTimeout::NONE).unwrap(); - /// let mut buf = [0u8; 80]; - /// read(&r, &mut buf[..]); /// ``` + /// These are placed in an array and passed to [`poll`] or [`ppoll`](fn.ppoll.html). // Unlike I/O functions, constructors like this must take `BorrowedFd` // instead of AsFd or &AsFd. Otherwise, an `OwnedFd` argument would be // dropped at the end of the method, leaving the structure referencing a @@ -61,7 +58,7 @@ impl<'fd> PollFd<'fd> { /// Returns the events that occurred in the last call to `poll` or `ppoll`. Will only return /// `None` if the kernel provides status flags that Nix does not know about. - pub fn revents(self) -> Option { + pub fn revents(&self) -> Option { PollFlags::from_bits(self.pollfd.revents) } @@ -71,7 +68,7 @@ impl<'fd> PollFd<'fd> { /// Equivalent to `x.revents()? != PollFlags::empty()`. /// /// This is marginally more efficient than [`PollFd::all`]. - pub fn any(self) -> Option { + pub fn any(&self) -> Option { Some(self.revents()? != PollFlags::empty()) } @@ -81,12 +78,12 @@ impl<'fd> PollFd<'fd> { /// Equivalent to `x.revents()? & x.events() == x.events()`. /// /// This is marginally less efficient than [`PollFd::any`]. - pub fn all(self) -> Option { + pub fn all(&self) -> Option { Some(self.revents()? & self.events() == self.events()) } /// The events of interest for this `PollFd`. - pub fn events(self) -> PollFlags { + pub fn events(&self) -> PollFlags { PollFlags::from_bits(self.pollfd.events).unwrap() } @@ -196,6 +193,34 @@ libc_bitflags! { /// in timeout means an infinite timeout. Specifying a timeout of /// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file /// descriptors are ready. +/// +/// The return value contains the number of `fds` which have selected events ([`PollFd::revents`]). +/// +/// # Examples +/// ```no_run +/// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd}; +/// # use nix::{ +/// # poll::{PollTimeout, PollFd, PollFlags, poll}, +/// # unistd::{pipe, read} +/// # }; +/// let (r0, w0) = pipe().unwrap(); +/// let (r1, w1) = pipe().unwrap(); +/// +/// let mut pollfds = [ +/// PollFd::new(r0.as_fd(), PollFlags::POLLIN), +/// PollFd::new(r1.as_fd(), PollFlags::POLLIN), +/// ]; +/// +/// let nready = poll(&mut pollfds, PollTimeout::NONE).unwrap(); +/// assert!(nready >= 1); // Since there is no timeout +/// +/// let mut buf = [0u8; 80]; +/// if pollfds[0].any().unwrap_or_default() { +/// read(&r0, &mut buf[..]); +/// } else if pollfds[1].any().unwrap_or_default() { +/// read(&r1, &mut buf[..]); +/// } +/// ``` pub fn poll>( fds: &mut [PollFd], timeout: T, @@ -217,7 +242,7 @@ feature! { /// descriptor becomes ready or until a signal is caught. /// ([`poll(2)`](https://man7.org/linux/man-pages/man2/poll.2.html)) /// -/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it +/// `ppoll` behaves like [`poll`], but let you specify what signals may interrupt it /// with the `sigmask` argument. If you want `ppoll` to block indefinitely, /// specify `None` as `timeout` (it is like `timeout = -1` for `poll`). /// If `sigmask` is `None`, then no signal mask manipulation is performed,