rustix/backend/libc/event/
poll_fd.rs

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