• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{event, sys, Events, Interest, Token};
2 use log::trace;
3 #[cfg(unix)]
4 use std::os::unix::io::{AsRawFd, RawFd};
5 use std::time::Duration;
6 use std::{fmt, io};
7 
8 /// Polls for readiness events on all registered values.
9 ///
10 /// `Poll` allows a program to monitor a large number of [`event::Source`]s,
11 /// waiting until one or more become "ready" for some class of operations; e.g.
12 /// reading and writing. An event source is considered ready if it is possible
13 /// to immediately perform a corresponding operation; e.g. [`read`] or
14 /// [`write`].
15 ///
16 /// To use `Poll`, an `event::Source` must first be registered with the `Poll`
17 /// instance using the [`register`] method on its associated `Register`,
18 /// supplying readiness interest. The readiness interest tells `Poll` which
19 /// specific operations on the handle to monitor for readiness. A `Token` is
20 /// also passed to the [`register`] function. When `Poll` returns a readiness
21 /// event, it will include this token.  This associates the event with the
22 /// event source that generated the event.
23 ///
24 /// [`event::Source`]: ./event/trait.Source.html
25 /// [`read`]: ./net/struct.TcpStream.html#method.read
26 /// [`write`]: ./net/struct.TcpStream.html#method.write
27 /// [`register`]: struct.Registry.html#method.register
28 ///
29 /// # Examples
30 ///
31 /// A basic example -- establishing a `TcpStream` connection.
32 ///
33 #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
34 #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
35 /// # use std::error::Error;
36 /// # fn main() -> Result<(), Box<dyn Error>> {
37 /// use mio::{Events, Poll, Interest, Token};
38 /// use mio::net::TcpStream;
39 ///
40 /// use std::net::{self, SocketAddr};
41 ///
42 /// // Bind a server socket to connect to.
43 /// let addr: SocketAddr = "127.0.0.1:0".parse()?;
44 /// let server = net::TcpListener::bind(addr)?;
45 ///
46 /// // Construct a new `Poll` handle as well as the `Events` we'll store into
47 /// let mut poll = Poll::new()?;
48 /// let mut events = Events::with_capacity(1024);
49 ///
50 /// // Connect the stream
51 /// let mut stream = TcpStream::connect(server.local_addr()?)?;
52 ///
53 /// // Register the stream with `Poll`
54 /// poll.registry().register(&mut stream, Token(0), Interest::READABLE | Interest::WRITABLE)?;
55 ///
56 /// // Wait for the socket to become ready. This has to happens in a loop to
57 /// // handle spurious wakeups.
58 /// loop {
59 ///     poll.poll(&mut events, None)?;
60 ///
61 ///     for event in &events {
62 ///         if event.token() == Token(0) && event.is_writable() {
63 ///             // The socket connected (probably, it could still be a spurious
64 ///             // wakeup)
65 ///             return Ok(());
66 ///         }
67 ///     }
68 /// }
69 /// # }
70 /// ```
71 ///
72 /// # Portability
73 ///
74 /// Using `Poll` provides a portable interface across supported platforms as
75 /// long as the caller takes the following into consideration:
76 ///
77 /// ### Spurious events
78 ///
79 /// [`Poll::poll`] may return readiness events even if the associated
80 /// event source is not actually ready. Given the same code, this may
81 /// happen more on some platforms than others. It is important to never assume
82 /// that, just because a readiness event was received, that the associated
83 /// operation will succeed as well.
84 ///
85 /// If operation fails with [`WouldBlock`], then the caller should not treat
86 /// this as an error, but instead should wait until another readiness event is
87 /// received.
88 ///
89 /// ### Draining readiness
90 ///
91 /// Once a readiness event is received, the corresponding operation must be
92 /// performed repeatedly until it returns [`WouldBlock`]. Unless this is done,
93 /// there is no guarantee that another readiness event will be delivered, even
94 /// if further data is received for the event source.
95 ///
96 /// [`WouldBlock`]: std::io::ErrorKind::WouldBlock
97 ///
98 /// ### Readiness operations
99 ///
100 /// The only readiness operations that are guaranteed to be present on all
101 /// supported platforms are [`readable`] and [`writable`]. All other readiness
102 /// operations may have false negatives and as such should be considered
103 /// **hints**. This means that if a socket is registered with [`readable`]
104 /// interest and either an error or close is received, a readiness event will
105 /// be generated for the socket, but it **may** only include `readable`
106 /// readiness. Also note that, given the potential for spurious events,
107 /// receiving a readiness event with `read_closed`, `write_closed`, or `error`
108 /// doesn't actually mean that a `read` on the socket will return a result
109 /// matching the readiness event.
110 ///
111 /// In other words, portable programs that explicitly check for [`read_closed`],
112 /// [`write_closed`], or [`error`] readiness should be doing so as an
113 /// **optimization** and always be able to handle an error or close situation
114 /// when performing the actual read operation.
115 ///
116 /// [`readable`]: ./event/struct.Event.html#method.is_readable
117 /// [`writable`]: ./event/struct.Event.html#method.is_writable
118 /// [`error`]: ./event/struct.Event.html#method.is_error
119 /// [`read_closed`]: ./event/struct.Event.html#method.is_read_closed
120 /// [`write_closed`]: ./event/struct.Event.html#method.is_write_closed
121 ///
122 /// ### Registering handles
123 ///
124 /// Unless otherwise noted, it should be assumed that types implementing
125 /// [`event::Source`] will never become ready unless they are registered with
126 /// `Poll`.
127 ///
128 /// For example:
129 ///
130 #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
131 #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
132 /// # use std::error::Error;
133 /// # use std::net;
134 /// # fn main() -> Result<(), Box<dyn Error>> {
135 /// use mio::{Poll, Interest, Token};
136 /// use mio::net::TcpStream;
137 /// use std::net::SocketAddr;
138 /// use std::time::Duration;
139 /// use std::thread;
140 ///
141 /// let address: SocketAddr = "127.0.0.1:0".parse()?;
142 /// let listener = net::TcpListener::bind(address)?;
143 /// let mut sock = TcpStream::connect(listener.local_addr()?)?;
144 ///
145 /// thread::sleep(Duration::from_secs(1));
146 ///
147 /// let poll = Poll::new()?;
148 ///
149 /// // The connect is not guaranteed to have started until it is registered at
150 /// // this point
151 /// poll.registry().register(&mut sock, Token(0), Interest::READABLE | Interest::WRITABLE)?;
152 /// #     Ok(())
153 /// # }
154 /// ```
155 ///
156 /// ### Dropping `Poll`
157 ///
158 /// When the `Poll` instance is dropped it may cancel in-flight operations for
159 /// the registered [event sources], meaning that no further events for them may
160 /// be received. It also means operations on the registered event sources may no
161 /// longer work. It is up to the user to keep the `Poll` instance alive while
162 /// registered event sources are being used.
163 ///
164 /// [event sources]: ./event/trait.Source.html
165 ///
166 /// ### Accessing raw fd/socket/handle
167 ///
168 /// Mio makes it possible for many types to be converted into a raw file
169 /// descriptor (fd, Unix), socket (Windows) or handle (Windows). This makes it
170 /// possible to support more operations on the type than Mio supports, for
171 /// example it makes [mio-aio] possible. However accessing the raw fd is not
172 /// without it's pitfalls.
173 ///
174 /// Specifically performing I/O operations outside of Mio on these types (via
175 /// the raw fd) has unspecified behaviour. It could cause no more events to be
176 /// generated for the type even though it returned `WouldBlock` (in an operation
177 /// directly accessing the fd). The behaviour is OS specific and Mio can only
178 /// guarantee cross-platform behaviour if it can control the I/O.
179 ///
180 /// [mio-aio]: https://github.com/asomers/mio-aio
181 ///
182 /// *The following is **not** guaranteed, just a description of the current
183 /// situation!* Mio is allowed to change the following without it being considered
184 /// a breaking change, don't depend on this, it's just here to inform the user.
185 /// Currently the kqueue and epoll implementation support direct I/O operations
186 /// on the fd without Mio's knowledge. Windows however needs **all** I/O
187 /// operations to go through Mio otherwise it is not able to update it's
188 /// internal state properly and won't generate events.
189 ///
190 /// ### Polling without registering event sources
191 ///
192 ///
193 /// *The following is **not** guaranteed, just a description of the current
194 /// situation!* Mio is allowed to change the following without it being
195 /// considered a breaking change, don't depend on this, it's just here to inform
196 /// the user. On platforms that use epoll, kqueue or IOCP (see implementation
197 /// notes below) polling without previously registering [event sources] will
198 /// result in sleeping forever, only a process signal will be able to wake up
199 /// the thread.
200 ///
201 /// On WASM/WASI this is different as it doesn't support process signals,
202 /// furthermore the WASI specification doesn't specify a behaviour in this
203 /// situation, thus it's up to the implementation what to do here. As an
204 /// example, the wasmtime runtime will return `EINVAL` in this situation, but
205 /// different runtimes may return different results. If you have further
206 /// insights or thoughts about this situation (and/or how Mio should handle it)
207 /// please add you comment to [pull request#1580].
208 ///
209 /// [event sources]: crate::event::Source
210 /// [pull request#1580]: https://github.com/tokio-rs/mio/pull/1580
211 ///
212 /// # Implementation notes
213 ///
214 /// `Poll` is backed by the selector provided by the operating system.
215 ///
216 /// |      OS       |  Selector |
217 /// |---------------|-----------|
218 /// | Android       | [epoll]   |
219 /// | DragonFly BSD | [kqueue]  |
220 /// | FreeBSD       | [kqueue]  |
221 /// | iOS           | [kqueue]  |
222 /// | illumos       | [epoll]   |
223 /// | Linux         | [epoll]   |
224 /// | NetBSD        | [kqueue]  |
225 /// | OpenBSD       | [kqueue]  |
226 /// | Windows       | [IOCP]    |
227 /// | macOS         | [kqueue]  |
228 ///
229 /// On all supported platforms, socket operations are handled by using the
230 /// system selector. Platform specific extensions (e.g. [`SourceFd`]) allow
231 /// accessing other features provided by individual system selectors. For
232 /// example, Linux's [`signalfd`] feature can be used by registering the FD with
233 /// `Poll` via [`SourceFd`].
234 ///
235 /// On all platforms except windows, a call to [`Poll::poll`] is mostly just a
236 /// direct call to the system selector. However, [IOCP] uses a completion model
237 /// instead of a readiness model. In this case, `Poll` must adapt the completion
238 /// model Mio's API. While non-trivial, the bridge layer is still quite
239 /// efficient. The most expensive part being calls to `read` and `write` require
240 /// data to be copied into an intermediate buffer before it is passed to the
241 /// kernel.
242 ///
243 /// [epoll]: https://man7.org/linux/man-pages/man7/epoll.7.html
244 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
245 /// [IOCP]: https://docs.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports
246 /// [`signalfd`]: https://man7.org/linux/man-pages/man2/signalfd.2.html
247 /// [`SourceFd`]: unix/struct.SourceFd.html
248 /// [`Poll::poll`]: struct.Poll.html#method.poll
249 pub struct Poll {
250     registry: Registry,
251 }
252 
253 /// Registers I/O resources.
254 pub struct Registry {
255     selector: sys::Selector,
256 }
257 
258 impl Poll {
259     cfg_os_poll! {
260         /// Return a new `Poll` handle.
261         ///
262         /// This function will make a syscall to the operating system to create
263         /// the system selector. If this syscall fails, `Poll::new` will return
264         /// with the error.
265         ///
266         /// close-on-exec flag is set on the file descriptors used by the selector to prevent
267         /// leaking it to executed processes. However, on some systems such as
268         /// old Linux systems that don't support `epoll_create1` syscall it is done
269         /// non-atomically, so a separate thread executing in parallel to this
270         /// function may accidentally leak the file descriptor if it executes a
271         /// new process before this function returns.
272         ///
273         /// See [struct] level docs for more details.
274         ///
275         /// [struct]: struct.Poll.html
276         ///
277         /// # Examples
278         ///
279         /// ```
280         /// # use std::error::Error;
281         /// # fn main() -> Result<(), Box<dyn Error>> {
282         /// use mio::{Poll, Events};
283         /// use std::time::Duration;
284         ///
285         /// let mut poll = match Poll::new() {
286         ///     Ok(poll) => poll,
287         ///     Err(e) => panic!("failed to create Poll instance; err={:?}", e),
288         /// };
289         ///
290         /// // Create a structure to receive polled events
291         /// let mut events = Events::with_capacity(1024);
292         ///
293         /// // Wait for events, but none will be received because no
294         /// // `event::Source`s have been registered with this `Poll` instance.
295         /// poll.poll(&mut events, Some(Duration::from_millis(500)))?;
296         /// assert!(events.is_empty());
297         /// #     Ok(())
298         /// # }
299         /// ```
300         pub fn new() -> io::Result<Poll> {
301             sys::Selector::new().map(|selector| Poll {
302                 registry: Registry { selector },
303             })
304         }
305     }
306 
307     /// Create a separate `Registry` which can be used to register
308     /// `event::Source`s.
registry(&self) -> &Registry309     pub fn registry(&self) -> &Registry {
310         &self.registry
311     }
312 
313     /// Wait for readiness events
314     ///
315     /// Blocks the current thread and waits for readiness events for any of the
316     /// [`event::Source`]s that have been registered with this `Poll` instance.
317     /// The function will block until either at least one readiness event has
318     /// been received or `timeout` has elapsed. A `timeout` of `None` means that
319     /// `poll` will block until a readiness event has been received.
320     ///
321     /// The supplied `events` will be cleared and newly received readiness events
322     /// will be pushed onto the end. At most `events.capacity()` events will be
323     /// returned. If there are further pending readiness events, they will be
324     /// returned on the next call to `poll`.
325     ///
326     /// A single call to `poll` may result in multiple readiness events being
327     /// returned for a single event source. For example, if a TCP socket becomes
328     /// both readable and writable, it may be possible for a single readiness
329     /// event to be returned with both [`readable`] and [`writable`] readiness
330     /// **OR** two separate events may be returned, one with [`readable`] set
331     /// and one with [`writable`] set.
332     ///
333     /// Note that the `timeout` will be rounded up to the system clock
334     /// granularity (usually 1ms), and kernel scheduling delays mean that
335     /// the blocking interval may be overrun by a small amount.
336     ///
337     /// See the [struct] level documentation for a higher level discussion of
338     /// polling.
339     ///
340     /// [`event::Source`]: ./event/trait.Source.html
341     /// [`readable`]: struct.Interest.html#associatedconstant.READABLE
342     /// [`writable`]: struct.Interest.html#associatedconstant.WRITABLE
343     /// [struct]: struct.Poll.html
344     /// [`iter`]: ./event/struct.Events.html#method.iter
345     ///
346     /// # Notes
347     ///
348     /// This returns any errors without attempting to retry, previous versions
349     /// of Mio would automatically retry the poll call if it was interrupted
350     /// (if `EINTR` was returned).
351     ///
352     /// Currently if the `timeout` elapses without any readiness events
353     /// triggering this will return `Ok(())`. However we're not guaranteeing
354     /// this behaviour as this depends on the OS.
355     ///
356     /// # Examples
357     ///
358     /// A basic example -- establishing a `TcpStream` connection.
359     ///
360     #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
361     #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
362     /// # use std::error::Error;
363     /// # fn main() -> Result<(), Box<dyn Error>> {
364     /// use mio::{Events, Poll, Interest, Token};
365     /// use mio::net::TcpStream;
366     ///
367     /// use std::net::{TcpListener, SocketAddr};
368     /// use std::thread;
369     ///
370     /// // Bind a server socket to connect to.
371     /// let addr: SocketAddr = "127.0.0.1:0".parse()?;
372     /// let server = TcpListener::bind(addr)?;
373     /// let addr = server.local_addr()?.clone();
374     ///
375     /// // Spawn a thread to accept the socket
376     /// thread::spawn(move || {
377     ///     let _ = server.accept();
378     /// });
379     ///
380     /// // Construct a new `Poll` handle as well as the `Events` we'll store into
381     /// let mut poll = Poll::new()?;
382     /// let mut events = Events::with_capacity(1024);
383     ///
384     /// // Connect the stream
385     /// let mut stream = TcpStream::connect(addr)?;
386     ///
387     /// // Register the stream with `Poll`
388     /// poll.registry().register(
389     ///     &mut stream,
390     ///     Token(0),
391     ///     Interest::READABLE | Interest::WRITABLE)?;
392     ///
393     /// // Wait for the socket to become ready. This has to happens in a loop to
394     /// // handle spurious wakeups.
395     /// loop {
396     ///     poll.poll(&mut events, None)?;
397     ///
398     ///     for event in &events {
399     ///         if event.token() == Token(0) && event.is_writable() {
400     ///             // The socket connected (probably, it could still be a spurious
401     ///             // wakeup)
402     ///             return Ok(());
403     ///         }
404     ///     }
405     /// }
406     /// # }
407     /// ```
408     ///
409     /// [struct]: #
poll(&mut self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()>410     pub fn poll(&mut self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
411         self.registry.selector.select(events.sys(), timeout)
412     }
413 }
414 
415 #[cfg(unix)]
416 impl AsRawFd for Poll {
as_raw_fd(&self) -> RawFd417     fn as_raw_fd(&self) -> RawFd {
418         self.registry.as_raw_fd()
419     }
420 }
421 
422 impl fmt::Debug for Poll {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result423     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
424         fmt.debug_struct("Poll").finish()
425     }
426 }
427 
428 impl Registry {
429     /// Register an [`event::Source`] with the `Poll` instance.
430     ///
431     /// Once registered, the `Poll` instance will monitor the event source for
432     /// readiness state changes. When it notices a state change, it will return
433     /// a readiness event for the handle the next time [`poll`] is called.
434     ///
435     /// See [`Poll`] docs for a high level overview.
436     ///
437     /// # Arguments
438     ///
439     /// `source: &mut S: event::Source`: This is the source of events that the
440     /// `Poll` instance should monitor for readiness state changes.
441     ///
442     /// `token: Token`: The caller picks a token to associate with the socket.
443     /// When [`poll`] returns an event for the handle, this token is included.
444     /// This allows the caller to map the event to its source. The token
445     /// associated with the `event::Source` can be changed at any time by
446     /// calling [`reregister`].
447     ///
448     /// See documentation on [`Token`] for an example showing how to pick
449     /// [`Token`] values.
450     ///
451     /// `interest: Interest`: Specifies which operations `Poll` should monitor
452     /// for readiness. `Poll` will only return readiness events for operations
453     /// specified by this argument.
454     ///
455     /// If a socket is registered with readable interest and the socket becomes
456     /// writable, no event will be returned from [`poll`].
457     ///
458     /// The readiness interest for an `event::Source` can be changed at any time
459     /// by calling [`reregister`].
460     ///
461     /// # Notes
462     ///
463     /// Callers must ensure that if a source being registered with a `Poll`
464     /// instance was previously registered with that `Poll` instance, then a
465     /// call to [`deregister`] has already occurred. Consecutive calls to
466     /// `register` is unspecified behavior.
467     ///
468     /// Unless otherwise specified, the caller should assume that once an event
469     /// source is registered with a `Poll` instance, it is bound to that `Poll`
470     /// instance for the lifetime of the event source. This remains true even
471     /// if the event source is deregistered from the poll instance using
472     /// [`deregister`].
473     ///
474     /// [`event::Source`]: ./event/trait.Source.html
475     /// [`poll`]: struct.Poll.html#method.poll
476     /// [`reregister`]: struct.Registry.html#method.reregister
477     /// [`deregister`]: struct.Registry.html#method.deregister
478     /// [`Token`]: struct.Token.html
479     ///
480     /// # Examples
481     ///
482     #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
483     #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
484     /// # use std::error::Error;
485     /// # use std::net;
486     /// # fn main() -> Result<(), Box<dyn Error>> {
487     /// use mio::{Events, Poll, Interest, Token};
488     /// use mio::net::TcpStream;
489     /// use std::net::SocketAddr;
490     /// use std::time::{Duration, Instant};
491     ///
492     /// let mut poll = Poll::new()?;
493     ///
494     /// let address: SocketAddr = "127.0.0.1:0".parse()?;
495     /// let listener = net::TcpListener::bind(address)?;
496     /// let mut socket = TcpStream::connect(listener.local_addr()?)?;
497     ///
498     /// // Register the socket with `poll`
499     /// poll.registry().register(
500     ///     &mut socket,
501     ///     Token(0),
502     ///     Interest::READABLE | Interest::WRITABLE)?;
503     ///
504     /// let mut events = Events::with_capacity(1024);
505     /// let start = Instant::now();
506     /// let timeout = Duration::from_millis(500);
507     ///
508     /// loop {
509     ///     let elapsed = start.elapsed();
510     ///
511     ///     if elapsed >= timeout {
512     ///         // Connection timed out
513     ///         return Ok(());
514     ///     }
515     ///
516     ///     let remaining = timeout - elapsed;
517     ///     poll.poll(&mut events, Some(remaining))?;
518     ///
519     ///     for event in &events {
520     ///         if event.token() == Token(0) {
521     ///             // Something (probably) happened on the socket.
522     ///             return Ok(());
523     ///         }
524     ///     }
525     /// }
526     /// # }
527     /// ```
register<S>(&self, source: &mut S, token: Token, interests: Interest) -> io::Result<()> where S: event::Source + ?Sized,528     pub fn register<S>(&self, source: &mut S, token: Token, interests: Interest) -> io::Result<()>
529     where
530         S: event::Source + ?Sized,
531     {
532         trace!(
533             "registering event source with poller: token={:?}, interests={:?}",
534             token,
535             interests
536         );
537         source.register(self, token, interests)
538     }
539 
540     /// Re-register an [`event::Source`] with the `Poll` instance.
541     ///
542     /// Re-registering an event source allows changing the details of the
543     /// registration. Specifically, it allows updating the associated `token`
544     /// and `interests` specified in previous `register` and `reregister` calls.
545     ///
546     /// The `reregister` arguments fully override the previous values. In other
547     /// words, if a socket is registered with [`readable`] interest and the call
548     /// to `reregister` specifies [`writable`], then read interest is no longer
549     /// requested for the handle.
550     ///
551     /// The event source must have previously been registered with this instance
552     /// of `Poll`, otherwise the behavior is unspecified.
553     ///
554     /// See the [`register`] documentation for details about the function
555     /// arguments and see the [`struct`] docs for a high level overview of
556     /// polling.
557     ///
558     /// # Examples
559     ///
560     #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
561     #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
562     /// # use std::error::Error;
563     /// # use std::net;
564     /// # fn main() -> Result<(), Box<dyn Error>> {
565     /// use mio::{Poll, Interest, Token};
566     /// use mio::net::TcpStream;
567     /// use std::net::SocketAddr;
568     ///
569     /// let poll = Poll::new()?;
570     ///
571     /// let address: SocketAddr = "127.0.0.1:0".parse()?;
572     /// let listener = net::TcpListener::bind(address)?;
573     /// let mut socket = TcpStream::connect(listener.local_addr()?)?;
574     ///
575     /// // Register the socket with `poll`, requesting readable
576     /// poll.registry().register(
577     ///     &mut socket,
578     ///     Token(0),
579     ///     Interest::READABLE)?;
580     ///
581     /// // Reregister the socket specifying write interest instead. Even though
582     /// // the token is the same it must be specified.
583     /// poll.registry().reregister(
584     ///     &mut socket,
585     ///     Token(0),
586     ///     Interest::WRITABLE)?;
587     /// #     Ok(())
588     /// # }
589     /// ```
590     ///
591     /// [`event::Source`]: ./event/trait.Source.html
592     /// [`struct`]: struct.Poll.html
593     /// [`register`]: struct.Registry.html#method.register
594     /// [`readable`]: ./event/struct.Event.html#is_readable
595     /// [`writable`]: ./event/struct.Event.html#is_writable
reregister<S>(&self, source: &mut S, token: Token, interests: Interest) -> io::Result<()> where S: event::Source + ?Sized,596     pub fn reregister<S>(&self, source: &mut S, token: Token, interests: Interest) -> io::Result<()>
597     where
598         S: event::Source + ?Sized,
599     {
600         trace!(
601             "reregistering event source with poller: token={:?}, interests={:?}",
602             token,
603             interests
604         );
605         source.reregister(self, token, interests)
606     }
607 
608     /// Deregister an [`event::Source`] with the `Poll` instance.
609     ///
610     /// When an event source is deregistered, the `Poll` instance will no longer
611     /// monitor it for readiness state changes. Deregistering clears up any
612     /// internal resources needed to track the handle.  After an explicit call
613     /// to this method completes, it is guaranteed that the token previously
614     /// registered to this handle will not be returned by a future poll, so long
615     /// as a happens-before relationship is established between this call and
616     /// the poll.
617     ///
618     /// The event source must have previously been registered with this instance
619     /// of `Poll`, otherwise the behavior is unspecified.
620     ///
621     /// A handle can be passed back to `register` after it has been
622     /// deregistered; however, it must be passed back to the **same** `Poll`
623     /// instance, otherwise the behavior is unspecified.
624     ///
625     /// # Examples
626     ///
627     #[cfg_attr(all(feature = "os-poll", feature = "net"), doc = "```")]
628     #[cfg_attr(not(all(feature = "os-poll", feature = "net")), doc = "```ignore")]
629     /// # use std::error::Error;
630     /// # use std::net;
631     /// # fn main() -> Result<(), Box<dyn Error>> {
632     /// use mio::{Events, Poll, Interest, Token};
633     /// use mio::net::TcpStream;
634     /// use std::net::SocketAddr;
635     /// use std::time::Duration;
636     ///
637     /// let mut poll = Poll::new()?;
638     ///
639     /// let address: SocketAddr = "127.0.0.1:0".parse()?;
640     /// let listener = net::TcpListener::bind(address)?;
641     /// let mut socket = TcpStream::connect(listener.local_addr()?)?;
642     ///
643     /// // Register the socket with `poll`
644     /// poll.registry().register(
645     ///     &mut socket,
646     ///     Token(0),
647     ///     Interest::READABLE)?;
648     ///
649     /// poll.registry().deregister(&mut socket)?;
650     ///
651     /// let mut events = Events::with_capacity(1024);
652     ///
653     /// // Set a timeout because this poll should never receive any events.
654     /// poll.poll(&mut events, Some(Duration::from_secs(1)))?;
655     /// assert!(events.is_empty());
656     /// #     Ok(())
657     /// # }
658     /// ```
deregister<S>(&self, source: &mut S) -> io::Result<()> where S: event::Source + ?Sized,659     pub fn deregister<S>(&self, source: &mut S) -> io::Result<()>
660     where
661         S: event::Source + ?Sized,
662     {
663         trace!("deregistering event source from poller");
664         source.deregister(self)
665     }
666 
667     /// Creates a new independently owned `Registry`.
668     ///
669     /// Event sources registered with this `Registry` will be registered with
670     /// the original `Registry` and `Poll` instance.
try_clone(&self) -> io::Result<Registry>671     pub fn try_clone(&self) -> io::Result<Registry> {
672         self.selector
673             .try_clone()
674             .map(|selector| Registry { selector })
675     }
676 
677     /// Internal check to ensure only a single `Waker` is active per [`Poll`]
678     /// instance.
679     #[cfg(all(debug_assertions, not(target_os = "wasi")))]
register_waker(&self)680     pub(crate) fn register_waker(&self) {
681         assert!(
682             !self.selector.register_waker(),
683             "Only a single `Waker` can be active per `Poll` instance"
684         );
685     }
686 
687     /// Get access to the `sys::Selector`.
688     #[cfg(any(not(target_os = "wasi"), feature = "net"))]
selector(&self) -> &sys::Selector689     pub(crate) fn selector(&self) -> &sys::Selector {
690         &self.selector
691     }
692 }
693 
694 impl fmt::Debug for Registry {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result695     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
696         fmt.debug_struct("Registry").finish()
697     }
698 }
699 
700 #[cfg(unix)]
701 impl AsRawFd for Registry {
as_raw_fd(&self) -> RawFd702     fn as_raw_fd(&self) -> RawFd {
703         self.selector.as_raw_fd()
704     }
705 }
706 
707 cfg_os_poll! {
708     #[cfg(unix)]
709     #[test]
710     pub fn as_raw_fd() {
711         let poll = Poll::new().unwrap();
712         assert!(poll.as_raw_fd() > 0);
713     }
714 }
715