use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd}; #[cfg(debug_assertions)] use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use std::{io, ptr};
use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLPRI, EPOLLRDHUP};
usecrate::{Interest, Token};
/// Unique id for use as `SelectorId`. #[cfg(debug_assertions)] static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
impl Selector { pubfn new() -> io::Result<Selector> { // SAFETY: `epoll_create1(2)` ensures the fd is valid. let ep = unsafe { OwnedFd::from_raw_fd(syscall!(epoll_create1(libc::EPOLL_CLOEXEC))?) };
Ok(Selector { #[cfg(debug_assertions)]
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
ep,
})
}
pubfn try_clone(&self) -> io::Result<Selector> { self.ep.try_clone().map(|ep| Selector { // It's the same selector, so we use the same id. #[cfg(debug_assertions)]
id: self.id,
ep,
})
}
pubfn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> { let timeout = timeout
.map(|to| { // `Duration::as_millis` truncates, so round up. This avoids // turning sub-millisecond timeouts into a zero timeout, unless // the caller explicitly requests that by specifying a zero // timeout.
to.checked_add(Duration::from_nanos(999_999))
.unwrap_or(to)
.as_millis() as libc::c_int
})
.unwrap_or(-1);
events.clear();
syscall!(epoll_wait( self.ep.as_raw_fd(),
events.as_mut_ptr(),
events.capacity() as i32,
timeout,
))
.map(|n_events| { // This is safe because `epoll_wait` ensures that `n_events` are // assigned. unsafe { events.set_len(n_events as usize) };
})
}
pubfn is_read_closed(event: &Event) -> bool { // Both halves of the socket have closed
event.events as libc::c_int & libc::EPOLLHUP != 0 // Socket has received FIN or called shutdown(SHUT_RD)
|| (event.events as libc::c_int & libc::EPOLLIN != 0
&& event.events as libc::c_int & libc::EPOLLRDHUP != 0)
}
pubfn is_write_closed(event: &Event) -> bool { // Both halves of the socket have closed
event.events as libc::c_int & libc::EPOLLHUP != 0 // Unix pipe write end has closed
|| (event.events as libc::c_int & libc::EPOLLOUT != 0
&& event.events as libc::c_int & libc::EPOLLERR != 0) // The other side (read end) of a Unix pipe has closed.
|| event.events as libc::c_int == libc::EPOLLERR
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.