summaryrefslogtreecommitdiffstats
path: root/vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs')
-rw-r--r--vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs366
1 files changed, 0 insertions, 366 deletions
diff --git a/vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs b/vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs
deleted file mode 100644
index 62a3c742b..000000000
--- a/vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs
+++ /dev/null
@@ -1,366 +0,0 @@
-//! epoll support.
-//!
-//! This is an experiment, and it isn't yet clear whether epoll is the right
-//! level of abstraction at which to introduce safety. But it works fairly well
-//! in simple examples 🙂.
-//!
-//! # Examples
-//!
-//! ```no_run
-//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
-//! # #[cfg(feature = "net")]
-//! # fn main() -> std::io::Result<()> {
-//! use io_lifetimes::AsFd;
-//! use rustix::io::{epoll, ioctl_fionbio, read, write};
-//! use rustix::net::{
-//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
-//! SocketType,
-//! };
-//! use std::collections::HashMap;
-//! use std::os::unix::io::AsRawFd;
-//!
-//! // Create a socket and listen on it.
-//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
-//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
-//! listen(&listen_sock, 1)?;
-//!
-//! // Create an epoll object. Using `Owning` here means the epoll object will
-//! // take ownership of the file descriptors registered with it.
-//! let epoll = epoll::epoll_create(epoll::CreateFlags::CLOEXEC)?;
-//!
-//! // Register the socket with the epoll object.
-//! epoll::epoll_add(&epoll, &listen_sock, 1, epoll::EventFlags::IN)?;
-//!
-//! // Keep track of the sockets we've opened.
-//! let mut next_id = 2;
-//! let mut sockets = HashMap::new();
-//!
-//! // Process events.
-//! let mut event_list = epoll::EventVec::with_capacity(4);
-//! loop {
-//! epoll::epoll_wait(&epoll, &mut event_list, -1)?;
-//! for (_event_flags, target) in &event_list {
-//! if target == 1 {
-//! // Accept a new connection, set it to non-blocking, and
-//! // register to be notified when it's ready to write to.
-//! let conn_sock = accept(&listen_sock)?;
-//! ioctl_fionbio(&conn_sock, true)?;
-//! epoll::epoll_add(
-//! &epoll,
-//! &conn_sock,
-//! next_id,
-//! epoll::EventFlags::OUT | epoll::EventFlags::ET,
-//! )?;
-//!
-//! // Keep track of the socket.
-//! sockets.insert(next_id, conn_sock);
-//! next_id += 1;
-//! } else {
-//! // Write a message to the stream and then unregister it.
-//! let target = sockets.remove(&target).unwrap();
-//! write(&target, b"hello\n")?;
-//! let _ = epoll::epoll_del(&epoll, &target)?;
-//! }
-//! }
-//! }
-//! # }
-//! # #[cfg(not(feature = "net"))]
-//! # fn main() {}
-//! ```
-
-use super::super::c;
-use super::super::conv::{ret, ret_owned_fd, ret_u32};
-use crate::fd::{AsFd, AsRawFd, OwnedFd};
-use crate::io;
-use alloc::vec::Vec;
-use bitflags::bitflags;
-use core::convert::TryInto;
-use core::ptr::null_mut;
-
-bitflags! {
- /// `EPOLL_*` for use with [`Epoll::new`].
- pub struct CreateFlags: c::c_int {
- /// `EPOLL_CLOEXEC`
- const CLOEXEC = c::EPOLL_CLOEXEC;
- }
-}
-
-bitflags! {
- /// `EPOLL*` for use with [`Epoll::add`].
- #[derive(Default)]
- pub struct EventFlags: u32 {
- /// `EPOLLIN`
- const IN = c::EPOLLIN as u32;
-
- /// `EPOLLOUT`
- const OUT = c::EPOLLOUT as u32;
-
- /// `EPOLLPRI`
- const PRI = c::EPOLLPRI as u32;
-
- /// `EPOLLERR`
- const ERR = c::EPOLLERR as u32;
-
- /// `EPOLLHUP`
- const HUP = c::EPOLLHUP as u32;
-
- /// `EPOLLRDNORM`
- const RDNORM = c::EPOLLRDNORM as u32;
-
- /// `EPOLLRDBAND`
- const RDBAND = c::EPOLLRDBAND as u32;
-
- /// `EPOLLWRNORM`
- const WRNORM = c::EPOLLWRNORM as u32;
-
- /// `EPOLLWRBAND`
- const WRBAND = c::EPOLLWRBAND as u32;
-
- /// `EPOLLMSG`
- const MSG = c::EPOLLMSG as u32;
-
- /// `EPOLLRDHUP`
- const RDHUP = c::EPOLLRDHUP as u32;
-
- /// `EPOLLET`
- const ET = c::EPOLLET as u32;
-
- /// `EPOLLONESHOT`
- const ONESHOT = c::EPOLLONESHOT as u32;
-
- /// `EPOLLWAKEUP`
- const WAKEUP = c::EPOLLWAKEUP as u32;
-
- /// `EPOLLEXCLUSIVE`
- #[cfg(not(target_os = "android"))]
- const EXCLUSIVE = c::EPOLLEXCLUSIVE as u32;
- }
-}
-
-/// `epoll_create1(flags)`—Creates a new `Epoll`.
-///
-/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
-/// descriptor from being implicitly passed across `exec` boundaries.
-#[inline]
-#[doc(alias = "epoll_create1")]
-pub fn epoll_create(flags: CreateFlags) -> io::Result<OwnedFd> {
- // SAFETY: We're calling `epoll_create1` via FFI and we know how it
- // behaves.
- unsafe { ret_owned_fd(c::epoll_create1(flags.bits())) }
-}
-
-/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
-/// `Epoll`.
-///
-/// Note that if `epoll_del` is not called on the I/O source passed into
-/// this function before the I/O source is `close`d, then the `epoll` will
-/// act as if the I/O source is still registered with it. This can lead to
-/// spurious events being returned from `epoll_wait`. If a file descriptor
-/// is an `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain
-/// a `Weak<dyn SystemResource>` to the file descriptor.
-#[doc(alias = "epoll_ctl")]
-pub fn epoll_add(
- epoll: impl AsFd,
- source: impl AsFd,
- data: u64,
- event_flags: EventFlags,
-) -> io::Result<()> {
- // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- let raw_fd = source.as_fd().as_raw_fd();
- ret(c::epoll_ctl(
- epoll.as_fd().as_raw_fd(),
- c::EPOLL_CTL_ADD,
- raw_fd,
- &mut c::epoll_event {
- events: event_flags.bits(),
- r#u64: data,
- },
- ))
- }
-}
-
-/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
-/// this `Epoll`.
-///
-/// This sets the events of interest with `target` to `events`.
-#[doc(alias = "epoll_ctl")]
-pub fn epoll_mod(
- epoll: impl AsFd,
- source: impl AsFd,
- data: u64,
- event_flags: EventFlags,
-) -> io::Result<()> {
- let raw_fd = source.as_fd().as_raw_fd();
-
- // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- ret(c::epoll_ctl(
- epoll.as_fd().as_raw_fd(),
- c::EPOLL_CTL_MOD,
- raw_fd,
- &mut c::epoll_event {
- events: event_flags.bits(),
- r#u64: data,
- },
- ))
- }
-}
-
-/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
-/// this `Epoll`.
-#[doc(alias = "epoll_ctl")]
-pub fn epoll_del(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
- // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
- // behaves.
- unsafe {
- let raw_fd = source.as_fd().as_raw_fd();
- ret(c::epoll_ctl(
- epoll.as_fd().as_raw_fd(),
- c::EPOLL_CTL_DEL,
- raw_fd,
- null_mut(),
- ))
- }
-}
-
-/// `epoll_wait(self, events, timeout)`—Waits for registered events of
-/// interest.
-///
-/// For each event of interest, an element is written to `events`. On
-/// success, this returns the number of written elements.
-pub fn epoll_wait(
- epoll: impl AsFd,
- event_list: &mut EventVec,
- timeout: c::c_int,
-) -> io::Result<()> {
- // SAFETY: We're calling `epoll_wait` via FFI and we know how it
- // behaves.
- unsafe {
- event_list.events.set_len(0);
- let nfds = ret_u32(c::epoll_wait(
- epoll.as_fd().as_raw_fd(),
- event_list.events.as_mut_ptr().cast::<c::epoll_event>(),
- event_list.events.capacity().try_into().unwrap_or(i32::MAX),
- timeout,
- ))?;
- event_list.events.set_len(nfds as usize);
- }
-
- Ok(())
-}
-
-/// An iterator over the `Event`s in an `EventVec`.
-pub struct Iter<'a> {
- iter: core::slice::Iter<'a, Event>,
-}
-
-impl<'a> Iterator for Iter<'a> {
- type Item = (EventFlags, u64);
-
- fn next(&mut self) -> Option<Self::Item> {
- // SAFETY: `self.context` is guaranteed to be valid because we hold
- // `'context` for it. And we know this event is associated with this
- // context because `wait` sets both.
- self.iter
- .next()
- .map(|event| (event.event_flags, event.data))
- }
-}
-
-/// A record of an event that occurred.
-#[repr(C)]
-#[cfg_attr(
- any(
- all(
- target_arch = "x86",
- not(target_env = "musl"),
- not(target_os = "android"),
- ),
- target_arch = "x86_64",
- ),
- repr(packed)
-)]
-struct Event {
- // Match the layout of `c::epoll_event`. We just use a `u64` instead of
- // the full union.
- event_flags: EventFlags,
- data: u64,
-}
-
-/// A vector of `Event`s, plus context for interpreting them.
-pub struct EventVec {
- events: Vec<Event>,
-}
-
-impl EventVec {
- /// Constructs an `EventVec` with memory for `capacity` `Event`s.
- #[inline]
- pub fn with_capacity(capacity: usize) -> Self {
- Self {
- events: Vec::with_capacity(capacity),
- }
- }
-
- /// Returns the current `Event` capacity of this `EventVec`.
- #[inline]
- pub fn capacity(&self) -> usize {
- self.events.capacity()
- }
-
- /// Reserves enough memory for at least `additional` more `Event`s.
- #[inline]
- pub fn reserve(&mut self, additional: usize) {
- self.events.reserve(additional);
- }
-
- /// Reserves enough memory for exactly `additional` more `Event`s.
- #[inline]
- pub fn reserve_exact(&mut self, additional: usize) {
- self.events.reserve_exact(additional);
- }
-
- /// Clears all the `Events` out of this `EventVec`.
- #[inline]
- pub fn clear(&mut self) {
- self.events.clear();
- }
-
- /// Shrinks the capacity of this `EventVec` as much as possible.
- #[inline]
- pub fn shrink_to_fit(&mut self) {
- self.events.shrink_to_fit();
- }
-
- /// Returns an iterator over the `Event`s in this `EventVec`.
- #[inline]
- pub fn iter(&self) -> Iter<'_> {
- Iter {
- iter: self.events.iter(),
- }
- }
-
- /// Returns the number of `Event`s logically contained in this `EventVec`.
- #[inline]
- pub fn len(&mut self) -> usize {
- self.events.len()
- }
-
- /// Tests whether this `EventVec` is logically empty.
- #[inline]
- pub fn is_empty(&mut self) -> bool {
- self.events.is_empty()
- }
-}
-
-impl<'a> IntoIterator for &'a EventVec {
- type IntoIter = Iter<'a>;
- type Item = (EventFlags, u64);
-
- #[inline]
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
- }
-}