pub struct Poll { /* private fields */ }
Expand description
Polls for readiness events on all registered values.
Poll
allows a program to monitor a large number of event::Source
s,
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 mio::{Events, Poll, Interest, Token};
use mio::net::TcpStream;
use std::net::{self, SocketAddr};
// Bind a server socket to connect to.
let addr: SocketAddr = "127.0.0.1:0".parse()?;
let server = net::TcpListener::bind(addr)?;
// Construct a new `Poll` handle as well as the `Events` we'll store into
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(1024);
// Connect the stream
let mut stream = TcpStream::connect(server.local_addr()?)?;
// Register the stream with `Poll`
poll.registry().register(&mut stream, Token(0), Interest::READABLE | Interest::WRITABLE)?;
// Wait for the socket to become ready. This has to happens in a loop to
// handle spurious wakeups.
loop {
poll.poll(&mut events, None)?;
for event in &events {
if event.token() == Token(0) && event.is_writable() {
// The socket connected (probably, it could still be a spurious
// wakeup)
return Ok(());
}
}
}
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 mio::{Poll, Interest, Token};
use mio::net::TcpStream;
use std::net::SocketAddr;
use std::time::Duration;
use std::thread;
let address: SocketAddr = "127.0.0.1:0".parse()?;
let listener = net::TcpListener::bind(address)?;
let mut sock = TcpStream::connect(listener.local_addr()?)?;
thread::sleep(Duration::from_secs(1));
let poll = Poll::new()?;
// The connect is not guaranteed to have started until it is registered at
// this point
poll.registry().register(&mut sock, Token(0), Interest::READABLE | Interest::WRITABLE)?;
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.
Implementation notes
Poll
is backed by the selector provided by the operating system.
OS | Selector |
---|---|
Android | epoll |
DragonFly BSD | kqueue |
FreeBSD | kqueue |
Linux | epoll |
NetBSD | kqueue |
OpenBSD | kqueue |
Solaris | epoll |
illumos | epoll |
Windows | IOCP |
iOS | kqueue |
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
sourceimpl Poll
impl Poll
sourcepub fn registry(&self) -> &Registry
pub fn registry(&self) -> &Registry
Create a separate Registry
which can be used to register
event::Source
s.
sourcepub fn poll(
&mut self,
events: &mut Events,
timeout: Option<Duration>
) -> Result<()>
pub fn poll(
&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::Source
s that have been registered with this Poll
instance.
The function will block until either at least one readiness event has
been received or timeout
has elapsed. A timeout
of None
means that
poll
will block until a readiness event has been received.
The supplied events
will be cleared and newly received readiness events
will be pushed onto the end. At most events.capacity()
events will be
returned. If there are further pending readiness events, they will be
returned on the next call to poll
.
A single call to poll
may 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 both readable
and writable
readiness
OR two separate events may be returned, one with readable
set
and one with writable
set.
Note that the timeout
will 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 EINTR
was returned).
Examples
A basic example – establishing a TcpStream
connection.
use mio::{Events, Poll, Interest, Token};
use mio::net::TcpStream;
use std::net::{TcpListener, SocketAddr};
use std::thread;
// Bind a server socket to connect to.
let addr: SocketAddr = "127.0.0.1:0".parse()?;
let server = TcpListener::bind(addr)?;
let addr = server.local_addr()?.clone();
// Spawn a thread to accept the socket
thread::spawn(move || {
let _ = server.accept();
});
// Construct a new `Poll` handle as well as the `Events` we'll store into
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(1024);
// Connect the stream
let mut stream = TcpStream::connect(addr)?;
// Register the stream with `Poll`
poll.registry().register(
&mut stream,
Token(0),
Interest::READABLE | Interest::WRITABLE)?;
// Wait for the socket to become ready. This has to happens in a loop to
// handle spurious wakeups.
loop {
poll.poll(&mut events, None)?;
for event in &events {
if event.token() == Token(0) && event.is_writable() {
// The socket connected (probably, it could still be a spurious
// wakeup)
return Ok(());
}
}
}
Trait Implementations
Auto Trait Implementations
impl RefUnwindSafe for Poll
impl Send for Poll
impl Sync for Poll
impl Unpin for Poll
impl UnwindSafe for Poll
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more