use std::ops::{Deref, DerefMut}; #[cfg(any(unix, target_os = "wasi"))] use std::os::fd::AsRawFd; // TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this // can use `std::os::fd` and be merged with the above. #[cfg(target_os = "hermit")] use std::os::hermit::io::AsRawFd; #[cfg(windows)] use std::os::windows::io::AsRawSocket; #[cfg(debug_assertions)] use std::sync::atomic::{AtomicUsize, Ordering}; use std::{fmt, io};
/// Adapter for a [`RawFd`] or [`RawSocket`] providing an [`event::Source`] /// implementation. /// /// `IoSource` enables registering any FD or socket wrapper with [`Poll`]. /// /// While only implementations for TCP, UDP, and UDS (Unix only) are provided, /// Mio supports registering any FD or socket that can be registered with the /// underlying OS selector. `IoSource` provides the necessary bridge. /// /// [`RawFd`]: std::os::fd::RawFd /// [`RawSocket`]: std::os::windows::io::RawSocket /// /// # Notes /// /// To handle the registrations and events properly **all** I/O operations (such /// as `read`, `write`, etc.) must go through the [`do_io`] method to ensure the /// internal state is updated accordingly. /// /// [`Poll`]: crate::Poll /// [`do_io`]: IoSource::do_io pubstruct IoSource<T> {
state: IoSourceState,
inner: T, #[cfg(debug_assertions)]
selector_id: SelectorId,
}
/// Execute an I/O operations ensuring that the socket receives more events /// if it hits a [`WouldBlock`] error. /// /// # Notes /// /// This method is required to be called for **all** I/O operations to /// ensure the user will receive events once the socket is ready again after /// returning a [`WouldBlock`] error. /// /// [`WouldBlock`]: io::ErrorKind::WouldBlock pubfn do_io<F, R>(&self, f: F) -> io::Result<R> where
F: FnOnce(&T) -> io::Result<R>,
{ self.state.do_io(f, &self.inner)
}
/// Returns the I/O source, dropping the state. /// /// # Notes /// /// To ensure no more events are to be received for this I/O source first /// [`deregister`] it. /// /// [`deregister`]: Registry::deregister pubfn into_inner(self) -> T { self.inner
}
}
/// Be careful when using this method. All I/O operations that may block must go /// through the [`do_io`] method. /// /// [`do_io`]: IoSource::do_io impl<T> Deref for IoSource<T> { type Target = T;
/// Be careful when using this method. All I/O operations that may block must go /// through the [`do_io`] method. /// /// [`do_io`]: IoSource::do_io impl<T> DerefMut for IoSource<T> { fn deref_mut(&mutself) -> &mutSelf::Target {
&mutself.inner
}
}
impl<T> fmt::Debug for IoSource<T> where
T: fmt::Debug,
{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f)
}
}
/// Used to associate an `IoSource` with a `sys::Selector`. #[cfg(debug_assertions)] #[derive(Debug)] struct SelectorId {
id: AtomicUsize,
}
#[cfg(debug_assertions)] impl SelectorId { /// Value of `id` if `SelectorId` is not associated with any /// `sys::Selector`. Valid selector ids start at 1. const UNASSOCIATED: usize = 0;
/// Create a new `SelectorId`. constfn new() -> SelectorId {
SelectorId {
id: AtomicUsize::new(Self::UNASSOCIATED),
}
}
/// Associate an I/O source with `registry`, returning an error if its /// already registered. fn associate(&self, registry: &Registry) -> io::Result<()> { let registry_id = registry.selector().id(); let previous_id = self.id.swap(registry_id, Ordering::AcqRel);
if previous_id == Self::UNASSOCIATED {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::AlreadyExists, "I/O source already registered with a `Registry`",
))
}
}
/// Check the association of an I/O source with `registry`, returning an /// error if its registered with a different `Registry` or not registered at /// all. fn check_association(&self, registry: &Registry) -> io::Result<()> { let registry_id = registry.selector().id(); let id = self.id.load(Ordering::Acquire);
if id == registry_id {
Ok(())
} elseif id == Self::UNASSOCIATED {
Err(io::Error::new(
io::ErrorKind::NotFound, "I/O source not registered with `Registry`",
))
} else {
Err(io::Error::new(
io::ErrorKind::AlreadyExists, "I/O source already registered with a different `Registry`",
))
}
}
/// Remove a previously made association from `registry`, returns an error /// if it was not previously associated with `registry`. fn remove_association(&self, registry: &Registry) -> io::Result<()> { let registry_id = registry.selector().id(); let previous_id = self.id.swap(Self::UNASSOCIATED, Ordering::AcqRel);
if previous_id == registry_id {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::NotFound, "I/O source not registered with `Registry`",
))
}
}
}
¤ 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.0.21Bemerkung:
(vorverarbeitet am 2026-06-18)
¤
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.