Skip to main content

dope_core/platform/
poll.rs

1use std::os::fd;
2
3use dope_sys::io::{poll, poll::Poll as _};
4use o3::alloc::{self, VecExt};
5
6use crate::{Backend, Errno};
7
8/// Owns readiness storage while borrowing every registered descriptor.
9pub struct Set<'fd> {
10    entries: Vec<poll::Entry<'fd>>,
11}
12
13impl<'fd> Set<'fd> {
14    pub fn try_new(
15        first: impl Iterator<Item = fd::BorrowedFd<'fd>>,
16        second: impl Iterator<Item = fd::BorrowedFd<'fd>>,
17    ) -> Result<Self, alloc::Error> {
18        let sources = first.chain(second);
19        let mut entries = Vec::try_new(sources.size_hint().0)?;
20        for source in sources {
21            alloc::Vacant::try_new(&mut entries)?.insert(poll::Entry::readable(source));
22        }
23        if poll::nfds_t::try_from(entries.len()).is_err() {
24            return Err(alloc::Error::Overflow);
25        }
26        Ok(Self { entries })
27    }
28
29    /// Borrows the exact first ready registration for handling or retirement.
30    pub fn poll(&mut self, timeout: i32) -> Result<Option<Ready<'_, 'fd>>, Errno> {
31        if Backend::wait::<_, Errno>(self, timeout)?.count() == 0 {
32            return Ok(None);
33        }
34        Ok(self
35            .entries
36            .iter_mut()
37            .enumerate()
38            .find_map(|(index, entry)| entry.is_ready().then_some(Ready { index, entry })))
39    }
40}
41
42/// Exclusive handling authority for one ready registration in its original set.
43pub struct Ready<'set, 'fd> {
44    index: usize,
45    entry: &'set mut poll::Entry<'fd>,
46}
47
48impl Ready<'_, '_> {
49    pub const fn index(&self) -> usize {
50        self.index
51    }
52
53    /// Retires this registration without changing any other registration's index.
54    pub fn retire(self) {
55        self.entry.retire();
56    }
57}
58
59// SAFETY: Set construction rejects any length exceeding nfds_t and its private
60// storage cannot grow after construction.
61unsafe impl<'fd> poll::raw::Entries<'fd> for Set<'fd> {
62    const MAX: usize = poll::MAX_ENTRIES;
63    fn entries(&mut self) -> &mut [poll::Entry<'fd>] {
64        &mut self.entries
65    }
66}