rustix/backend/libc/event/
poll_fd.rs

1use crate::backend::c;
2use crate::backend::conv::borrowed_fd;
3use crate::backend::fd::{AsFd, AsRawFd as _, BorrowedFd, LibcFd};
4#[cfg(windows)]
5use crate::backend::fd::{AsSocket, RawFd};
6use crate::ffi;
7use bitflags::bitflags;
8use core::fmt;
9use core::marker::PhantomData;
10
11bitflags! {
12    /// `POLL*` flags for use with [`poll`].
13    ///
14    /// [`poll`]: crate::event::poll
15    #[repr(transparent)]
16    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
17    pub struct PollFlags: ffi::c_short {
18        /// `POLLIN`
19        const IN = c::POLLIN;
20        /// `POLLPRI`
21        #[cfg(not(target_os = "wasi"))]
22        const PRI = c::POLLPRI;
23        /// `POLLOUT`
24        const OUT = c::POLLOUT;
25        /// `POLLRDNORM`
26        const RDNORM = c::POLLRDNORM;
27        /// `POLLWRNORM`
28        #[cfg(not(target_os = "l4re"))]
29        const WRNORM = c::POLLWRNORM;
30        /// `POLLRDBAND`
31        #[cfg(not(any(target_os = "l4re", target_os = "wasi")))]
32        const RDBAND = c::POLLRDBAND;
33        /// `POLLWRBAND`
34        #[cfg(not(any(target_os = "l4re", target_os = "wasi")))]
35        const WRBAND = c::POLLWRBAND;
36        /// `POLLERR`
37        const ERR = c::POLLERR;
38        /// `POLLHUP`
39        const HUP = c::POLLHUP;
40        /// `POLLNVAL`
41        #[cfg(not(target_os = "espidf"))]
42        const NVAL = c::POLLNVAL;
43        /// `POLLRDHUP`
44        #[cfg(any(
45            target_os = "freebsd",
46            target_os = "illumos",
47            all(
48                linux_kernel,
49                not(any(target_arch = "sparc", target_arch = "sparc64"))
50            ),
51        ))]
52        const RDHUP = c::POLLRDHUP;
53
54        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
55        const _ = !0;
56    }
57}
58
59/// `struct pollfd`—File descriptor and flags for use with [`poll`].
60///
61/// [`poll`]: crate::event::poll
62#[doc(alias = "pollfd")]
63#[derive(Clone)]
64#[repr(transparent)]
65pub struct PollFd<'fd> {
66    pollfd: c::pollfd,
67    _phantom: PhantomData<BorrowedFd<'fd>>,
68}
69
70impl<'fd> fmt::Debug for PollFd<'fd> {
71    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72        f.debug_struct("PollFd")
73            .field("fd", &self.pollfd.fd)
74            .field("events", &self.pollfd.events)
75            .field("revents", &self.pollfd.revents)
76            .finish()
77    }
78}
79
80impl<'fd> PollFd<'fd> {
81    /// Constructs a new `PollFd` holding `fd` and `events`.
82    #[inline]
83    pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
84        Self::from_borrowed_fd(fd.as_fd(), events)
85    }
86
87    /// Sets the contained file descriptor to `fd`.
88    #[inline]
89    pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
90        self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd;
91    }
92
93    /// Clears the ready events.
94    #[inline]
95    pub fn clear_revents(&mut self) {
96        self.pollfd.revents = 0;
97    }
98
99    /// Constructs a new `PollFd` holding `fd` and `events`.
100    ///
101    /// This is the same as `new`, but can be used to avoid borrowing the
102    /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
103    /// is a temporary.
104    #[inline]
105    pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
106        Self {
107            pollfd: c::pollfd {
108                fd: borrowed_fd(fd),
109                events: events.bits(),
110                revents: 0,
111            },
112            _phantom: PhantomData,
113        }
114    }
115
116    /// Returns the ready events.
117    #[inline]
118    pub fn revents(&self) -> PollFlags {
119        // Use `.unwrap()` here because in theory we know we know all the bits
120        // the OS might set here, but OS's have added extensions in the past.
121        PollFlags::from_bits(self.pollfd.revents).unwrap()
122    }
123}
124
125#[cfg(not(windows))]
126impl<'fd> AsFd for PollFd<'fd> {
127    #[inline]
128    fn as_fd(&self) -> BorrowedFd<'_> {
129        // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be
130        // valid for the `'fd` lifetime.
131        unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) }
132    }
133}
134
135#[cfg(windows)]
136impl<'fd> AsSocket for PollFd<'fd> {
137    #[inline]
138    fn as_socket(&self) -> BorrowedFd<'_> {
139        // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be
140        // valid for the `'fd` lifetime.
141        unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) }
142    }
143}