1use std::{
2 marker,
3 os::fd::{AsRawFd as _, BorrowedFd},
4 slice,
5};
6
7pub use libc::nfds_t;
8
9use o3::base::marker::ThreadBound;
10
11use crate::{
12 Errno,
13 io::poll,
14 kernel::{self, errno},
15};
16
17pub mod raw;
18
19pub const MAX_ENTRIES: usize = nfds_t::MAX as usize;
21
22#[derive(Clone, Copy, Debug)]
24#[repr(transparent)]
25pub struct Entry<'fd>(
26 libc::pollfd,
27 marker::PhantomData<(BorrowedFd<'fd>, ThreadBound)>,
28);
29
30impl<'fd> Entry<'fd> {
31 pub fn readable(fd: BorrowedFd<'fd>) -> Self {
33 Self::new(fd, libc::POLLIN)
34 }
35
36 pub fn writable(fd: BorrowedFd<'fd>) -> Self {
38 Self::new(fd, libc::POLLOUT)
39 }
40
41 fn new(fd: BorrowedFd<'fd>, events: libc::c_short) -> Self {
42 Self(
43 libc::pollfd {
44 fd: fd.as_raw_fd(),
45 events,
46 revents: 0,
47 },
48 marker::PhantomData,
49 )
50 }
51
52 pub const fn is_ready(self) -> bool {
54 self.0.revents != 0
55 }
56
57 pub const fn is_readable(self) -> bool {
59 self.0.revents & libc::POLLIN != 0
60 }
61
62 pub const fn revents(self) -> i16 {
64 self.0.revents
65 }
66
67 pub fn retire(&mut self) {
69 self.0.fd = -1;
70 self.0.revents = 0;
71 }
72}
73
74fn raw<'a>(entries: &'a mut [Entry<'_>]) -> &'a mut [libc::pollfd] {
76 unsafe { slice::from_raw_parts_mut(entries.as_mut_ptr().cast(), entries.len()) }
79}
80
81pub struct Events<'a, 'fd> {
82 entries: &'a [Entry<'fd>],
83 count: usize,
84}
85
86impl<'a, 'fd> Events<'a, 'fd> {
87 pub const fn count(&self) -> usize {
88 self.count
89 }
90 pub const fn entries(&self) -> &'a [Entry<'fd>] {
91 self.entries
92 }
93}
94
95pub trait Poll: errno::Source {
97 fn wait<'a, 'fd: 'a, T: poll::raw::Entries<'fd>, E: From<Errno>>(
98 owner: &'a mut T,
99 timeout: i32,
100 ) -> Result<poll::Events<'a, 'fd>, E> {
101 const {
102 assert!(T::MAX as nfds_t as usize == T::MAX);
103 }
104 let entries = owner.entries();
105 let raw = raw(entries);
106 let raw = unsafe { libc::poll(raw.as_mut_ptr(), raw.len() as nfds_t, timeout) };
108 let count = unsafe { kernel::raw::Status::new(raw).try_count::<Self, E>() }?.get();
110 Ok(poll::Events { entries, count })
111 }
112}
113
114impl<T: errno::Source> Poll for T {}