Struct Poll
struct Poll { ... }
Polls for readiness events on all registered values.
Poll allows a program to monitor a large number of event::Sources,
waiting until one or more become "ready" for some class of operations; e.g.
reading and writing. An event source is considered ready if it is possible
to immediately perform a corresponding operation; e.g. read or
write.
To use Poll, an event::Source must first be registered with the Poll
instance using the register method on its associated Register,
supplying readiness interest. The readiness interest tells Poll which
specific operations on the handle to monitor for readiness. A Token is
also passed to the register function. When Poll returns a readiness
event, it will include this token. This associates the event with the
event source that generated the event.
Examples
A basic example -- establishing a TcpStream connection.
# use Error;
#
Portability
Using Poll provides a portable interface across supported platforms as
long as the caller takes the following into consideration:
Spurious events
Poll::poll may return readiness events even if the associated
event source is not actually ready. Given the same code, this may
happen more on some platforms than others. It is important to never assume
that, just because a readiness event was received, that the associated
operation will succeed as well.
If operation fails with WouldBlock, then the caller should not treat
this as an error, but instead should wait until another readiness event is
received.
Draining readiness
Once a readiness event is received, the corresponding operation must be
performed repeatedly until it returns WouldBlock. Unless this is done,
there is no guarantee that another readiness event will be delivered, even
if further data is received for the event source.
Readiness operations
The only readiness operations that are guaranteed to be present on all
supported platforms are readable and writable. All other readiness
operations may have false negatives and as such should be considered
hints. This means that if a socket is registered with readable
interest and either an error or close is received, a readiness event will
be generated for the socket, but it may only include readable
readiness. Also note that, given the potential for spurious events,
receiving a readiness event with read_closed, write_closed, or error
doesn't actually mean that a read on the socket will return a result
matching the readiness event.
In other words, portable programs that explicitly check for read_closed,
write_closed, or error readiness should be doing so as an
optimization and always be able to handle an error or close situation
when performing the actual read operation.
Registering handles
Unless otherwise noted, it should be assumed that types implementing
event::Source will never become ready unless they are registered with
Poll.
For example:
# use Error;
# use net;
#
Dropping Poll
When the Poll instance is dropped it may cancel in-flight operations for
the registered event sources, meaning that no further events for them may
be received. It also means operations on the registered event sources may no
longer work. It is up to the user to keep the Poll instance alive while
registered event sources are being used.
Accessing raw fd/socket/handle
Mio makes it possible for many types to be converted into a raw file descriptor (fd, Unix), socket (Windows) or handle (Windows). This makes it possible to support more operations on the type than Mio supports, for example it makes mio-aio possible. However accessing the raw fd is not without it's pitfalls.
Specifically performing I/O operations outside of Mio on these types (via
the raw fd) has unspecified behaviour. It could cause no more events to be
generated for the type even though it returned WouldBlock (in an operation
directly accessing the fd). The behaviour is OS specific and Mio can only
guarantee cross-platform behaviour if it can control the I/O.
The following is not guaranteed, just a description of the current situation! Mio is allowed to change the following without it being considered a breaking change, don't depend on this, it's just here to inform the user. Currently the kqueue and epoll implementation support direct I/O operations on the fd without Mio's knowledge. Windows however needs all I/O operations to go through Mio otherwise it is not able to update it's internal state properly and won't generate events.
Polling without registering event sources
The following is not guaranteed, just a description of the current situation! Mio is allowed to change the following without it being considered a breaking change, don't depend on this, it's just here to inform the user. On platforms that use epoll, kqueue or IOCP (see implementation notes below) polling without previously registering event sources will result in sleeping forever, only a process signal will be able to wake up the thread.
On WASM/WASI this is different as it doesn't support process signals,
furthermore the WASI specification doesn't specify a behaviour in this
situation, thus it's up to the implementation what to do here. As an
example, the wasmtime runtime will return EINVAL in this situation, but
different runtimes may return different results. If you have further
insights or thoughts about this situation (and/or how Mio should handle it)
please add you comment to pull request#1580.
Implementation notes
Poll is backed by the selector provided by the operating system.
| OS | Selector |
|---|---|
| Android | epoll |
| DragonFly BSD | kqueue |
| FreeBSD | kqueue |
| iOS | kqueue |
| illumos | epoll |
| Linux | epoll |
| NetBSD | kqueue |
| OpenBSD | kqueue |
| Windows | IOCP |
| macOS | kqueue |
On all supported platforms, socket operations are handled by using the
system selector. Platform specific extensions (e.g. SourceFd) allow
accessing other features provided by individual system selectors. For
example, Linux's signalfd feature can be used by registering the FD with
Poll via SourceFd.
On all platforms except windows, a call to Poll::poll is mostly just a
direct call to the system selector. However, IOCP uses a completion model
instead of a readiness model. In this case, Poll must adapt the completion
model Mio's API. While non-trivial, the bridge layer is still quite
efficient. The most expensive part being calls to read and write require
data to be copied into an intermediate buffer before it is passed to the
kernel.
Implementations
impl Poll
fn new() -> Result<Poll>Return a new
Pollhandle.This function will make a syscall to the operating system to create the system selector. If this syscall fails,
Poll::newwill return with the error.close-on-exec flag is set on the file descriptors used by the selector to prevent leaking it to executed processes. However, on some systems such as old Linux systems that don't support
epoll_create1syscall it is done non-atomically, so a separate thread executing in parallel to this function may accidentally leak the file descriptor if it executes a new process before this function returns.See struct level docs for more details.
Examples
# use Error; #fn registry(self: &Self) -> &RegistryReturns a
Registrywhich can be used to registerevent::Sources.fn poll(self: &mut Self, events: &mut Events, timeout: Option<Duration>) -> Result<()>Wait for readiness events
Blocks the current thread and waits for readiness events for any of the
event::Sources that have been registered with thisPollinstance. The function will block until either at least one readiness event has been received ortimeouthas elapsed. AtimeoutofNonemeans thatpollwill block until a readiness event has been received.The supplied
eventswill be cleared and newly received readiness events will be pushed onto the end. At mostevents.capacity()events will be returned. If there are further pending readiness events, they will be returned on the next call topoll.A single call to
pollmay result in multiple readiness events being returned for a single event source. For example, if a TCP socket becomes both readable and writable, it may be possible for a single readiness event to be returned with bothreadableandwritablereadiness OR two separate events may be returned, one withreadableset and one withwritableset.Note that the
timeoutwill be rounded up to the system clock granularity (usually 1ms), and kernel scheduling delays mean that the blocking interval may be overrun by a small amount.See the struct level documentation for a higher level discussion of polling.
Notes
This returns any errors without attempting to retry, previous versions of Mio would automatically retry the poll call if it was interrupted (if
EINTRwas returned).Currently if the
timeoutelapses without any readiness events triggering this will returnOk(()). However we're not guaranteeing this behaviour as this depends on the OS.Examples
A basic example -- establishing a
TcpStreamconnection.# use Error; #
impl AsRawFd for Poll
fn as_raw_fd(self: &Self) -> RawFd
impl Debug for Poll
fn fmt(self: &Self, fmt: &mut Formatter<'_>) -> Result
impl Freeze for Poll
impl RefUnwindSafe for Poll
impl Send for Poll
impl Sync for Poll
impl Unpin for Poll
impl UnsafeUnpin for Poll
impl UnwindSafe for Poll
impl<T> Any for Poll
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for Poll
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for Poll
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> From for Poll
fn from(t: T) -> TReturns the argument unchanged.
impl<T, U> Into for Poll
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for Poll
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for Poll
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>