//! # Notes //! //! The current implementation is somewhat limited. The `Waker` is not //! implemented, as at the time of writing there is no way to support to wake-up //! a thread from calling `poll_oneoff`. //! //! Furthermore the (re/de)register functions also don't work while concurrently //! polling as both registering and polling requires a lock on the //! `subscriptions`. //! //! Finally `Selector::try_clone`, required by `Registry::try_clone`, doesn't //! work. However this could be implemented by use of an `Arc`. //! //! In summary, this only (barely) works using a single thread.
use std::cmp::min; use std::io; #[cfg(all(feature = "net", debug_assertions))] use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::time::Duration;
// If we want to a use a timeout in the `wasi_poll_oneoff()` function // we need another subscription to the list. iflet Some(timeout) = timeout {
subscriptions.push(timeout_subscription(timeout));
}
// `poll_oneoff` needs the same number of events as subscriptions. let length = subscriptions.len();
events.reserve(length);
debug_assert!(events.capacity() >= length); #[cfg(debug_assertions)] if length == 0 {
warn!( "calling mio::Poll::poll with empty subscriptions, this likely not what you want"
);
}
let res = unsafe { wasi::poll_oneoff(subscriptions.as_ptr(), events.as_mut_ptr(), length) };
// Remove the timeout subscription we possibly added above. if timeout.is_some() { let timeout_sub = subscriptions.pop();
debug_assert_eq!(
timeout_sub.unwrap().u.tag,
wasi::EVENTTYPE_CLOCK.raw(), "failed to remove timeout subscription"
);
}
drop(subscriptions); // Unlock.
match res {
Ok(n_events) => { // Safety: `poll_oneoff` initialises the `events` for us. unsafe { events.set_len(n_events) };
// Remove the timeout event. if timeout.is_some() { iflet Some(index) = events.iter().position(is_timeout_event) {
events.swap_remove(index);
}
}
let predicate = |subscription: &wasi::Subscription| { // Safety: `subscription.u.tag` defines the type of the union in // `subscription.u.u`. match subscription.u.tag {
t if t == wasi::EVENTTYPE_FD_WRITE.raw() => unsafe {
subscription.u.u.fd_write.file_descriptor == fd
},
t if t == wasi::EVENTTYPE_FD_READ.raw() => unsafe {
subscription.u.u.fd_read.file_descriptor == fd
},
_ => false,
}
};
letmut ret = Err(io::ErrorKind::NotFound.into());
whilelet Some(index) = subscriptions.iter().position(predicate) {
subscriptions.swap_remove(index);
ret = Ok(())
}
ret
}
}
/// Token used to a add a timeout subscription, also used in removing it again. const TIMEOUT_TOKEN: wasi::Userdata = wasi::Userdata::MAX;
/// Returns a `wasi::Subscription` for `timeout`. fn timeout_subscription(timeout: Duration) -> wasi::Subscription {
wasi::Subscription {
userdata: TIMEOUT_TOKEN,
u: wasi::SubscriptionU {
tag: wasi::EVENTTYPE_CLOCK.raw(),
u: wasi::SubscriptionUU {
clock: wasi::SubscriptionClock {
id: wasi::CLOCKID_MONOTONIC, // Timestamp is in nanoseconds.
timeout: min(wasi::Timestamp::MAX as u128, timeout.as_nanos()) as wasi::Timestamp, // Give the implementation another millisecond to coalesce // events.
precision: Duration::from_millis(1).as_nanos() as wasi::Timestamp, // Zero means the `timeout` is considered relative to the // current time.
flags: 0,
},
},
},
}
}
/// Check all events for possible errors, it returns the first error found. fn check_errors(events: &[Event]) -> io::Result<()> { for event in events { if event.error != wasi::ERRNO_SUCCESS { return Err(io_err(event.error));
}
}
Ok(())
}
/// Convert `wasi::Errno` into an `io::Error`. fn io_err(errno: wasi::Errno) -> io::Error { // TODO: check if this is valid.
io::Error::from_raw_os_error(errno.raw() as i32)
}
pub(crate) fn is_error(_: &Event) -> bool { // Not supported? It could be that `wasi::Event.error` could be used for // this, but the docs say `error that occurred while processing the // subscription request`, so it's checked in `Select::select` already. false
}
pub(crate) fn is_read_closed(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_READ // Safety: checked the type of the union above.
&& (event.fd_readwrite.flags & wasi::EVENTRWFLAGS_FD_READWRITE_HANGUP) != 0
}
pub(crate) fn is_write_closed(event: &Event) -> bool {
event.type_ == wasi::EVENTTYPE_FD_WRITE // Safety: checked the type of the union above.
&& (event.fd_readwrite.flags & wasi::EVENTRWFLAGS_FD_READWRITE_HANGUP) != 0
}
pub(crate) fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R> where
F: FnOnce(&T) -> io::Result<R>,
{ // We don't hold state, so we can just call the function and // return.
f(io)
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.11 Sekunden
(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.