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