1 use crate::{sys, Token}; 2 3 use std::fmt; 4 5 /// A readiness event. 6 /// 7 /// `Event` is a readiness state paired with a [`Token`]. It is returned by 8 /// [`Poll::poll`]. 9 /// 10 /// For more documentation on polling and events, see [`Poll`]. 11 /// 12 /// [`Poll::poll`]: ../struct.Poll.html#method.poll 13 /// [`Poll`]: ../struct.Poll.html 14 /// [`Token`]: ../struct.Token.html 15 #[derive(Clone)] 16 #[repr(transparent)] 17 pub struct Event { 18 inner: sys::Event, 19 } 20 21 impl Event { 22 /// Returns the event's token. token(&self) -> Token23 pub fn token(&self) -> Token { 24 sys::event::token(&self.inner) 25 } 26 27 /// Returns true if the event contains readable readiness. is_readable(&self) -> bool28 pub fn is_readable(&self) -> bool { 29 sys::event::is_readable(&self.inner) 30 } 31 32 /// Returns true if the event contains writable readiness. is_writable(&self) -> bool33 pub fn is_writable(&self) -> bool { 34 sys::event::is_writable(&self.inner) 35 } 36 37 /// Returns true if the event contains error readiness. 38 /// 39 /// Error events occur when the socket enters an error state. In this case, 40 /// the socket will also receive a readable or writable event. Reading or 41 /// writing to the socket will result in an error. 42 /// 43 /// # Notes 44 /// 45 /// Method is available on all platforms, but not all platforms trigger the 46 /// error event. 47 /// 48 /// The table below shows what flags are checked on what OS. 49 /// 50 /// | [OS selector] | Flag(s) checked | 51 /// |---------------|-----------------| 52 /// | [epoll] | `EPOLLERR` | 53 /// | [kqueue] | `EV_ERROR` and `EV_EOF` with `fflags` set to `0`. | 54 /// 55 /// [OS selector]: ../struct.Poll.html#implementation-notes 56 /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html 57 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 is_error(&self) -> bool58 pub fn is_error(&self) -> bool { 59 sys::event::is_error(&self.inner) 60 } 61 62 /// Returns true if the event contains read closed readiness. 63 /// 64 /// # Notes 65 /// 66 /// Read closed readiness can be expected after any of the following have 67 /// occurred: 68 /// * The local stream has shutdown the read half of its socket 69 /// * The local stream has shutdown both the read half and the write half 70 /// of its socket 71 /// * The peer stream has shutdown the write half its socket; this sends a 72 /// `FIN` packet that has been received by the local stream 73 /// 74 /// Method is a best effort implementation. While some platforms may not 75 /// return readiness when read half is closed, it is guaranteed that 76 /// false-positives will not occur. 77 /// 78 /// The table below shows what flags are checked on what OS. 79 /// 80 /// | [OS selector] | Flag(s) checked | 81 /// |---------------|-----------------| 82 /// | [epoll] | `EPOLLHUP`, or | 83 /// | | `EPOLLIN` and `EPOLLRDHUP` | 84 /// | [kqueue] | `EV_EOF` | 85 /// 86 /// [OS selector]: ../struct.Poll.html#implementation-notes 87 /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html 88 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 is_read_closed(&self) -> bool89 pub fn is_read_closed(&self) -> bool { 90 sys::event::is_read_closed(&self.inner) 91 } 92 93 /// Returns true if the event contains write closed readiness. 94 /// 95 /// # Notes 96 /// 97 /// On [epoll] this is essentially a check for `EPOLLHUP` flag as the 98 /// local stream shutting down its write half does not trigger this event. 99 /// 100 /// On [kqueue] the local stream shutting down the write half of its 101 /// socket will trigger this event. 102 /// 103 /// Method is a best effort implementation. While some platforms may not 104 /// return readiness when write half is closed, it is guaranteed that 105 /// false-positives will not occur. 106 /// 107 /// The table below shows what flags are checked on what OS. 108 /// 109 /// | [OS selector] | Flag(s) checked | 110 /// |---------------|-----------------| 111 /// | [epoll] | `EPOLLHUP`, or | 112 /// | | only `EPOLLERR`, or | 113 /// | | `EPOLLOUT` and `EPOLLERR` | 114 /// | [kqueue] | `EV_EOF` | 115 /// 116 /// [OS selector]: ../struct.Poll.html#implementation-notes 117 /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html 118 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 is_write_closed(&self) -> bool119 pub fn is_write_closed(&self) -> bool { 120 sys::event::is_write_closed(&self.inner) 121 } 122 123 /// Returns true if the event contains priority readiness. 124 /// 125 /// # Notes 126 /// 127 /// Method is available on all platforms, but not all platforms trigger the 128 /// priority event. 129 /// 130 /// The table below shows what flags are checked on what OS. 131 /// 132 /// | [OS selector] | Flag(s) checked | 133 /// |---------------|-----------------| 134 /// | [epoll] | `EPOLLPRI` | 135 /// | [kqueue] | *Not supported* | 136 /// 137 /// [OS selector]: ../struct.Poll.html#implementation-notes 138 /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html 139 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 140 #[inline] is_priority(&self) -> bool141 pub fn is_priority(&self) -> bool { 142 sys::event::is_priority(&self.inner) 143 } 144 145 /// Returns true if the event contains AIO readiness. 146 /// 147 /// # Notes 148 /// 149 /// Method is available on all platforms, but not all platforms support AIO. 150 /// 151 /// The table below shows what flags are checked on what OS. 152 /// 153 /// | [OS selector] | Flag(s) checked | 154 /// |---------------|-----------------| 155 /// | [epoll] | *Not supported* | 156 /// | [kqueue]<sup>1</sup> | `EVFILT_AIO` | 157 /// 158 /// 1: Only supported on DragonFly BSD, FreeBSD, iOS and macOS. 159 /// 160 /// [OS selector]: ../struct.Poll.html#implementation-notes 161 /// [epoll]: http://man7.org/linux/man-pages/man7/epoll.7.html 162 /// [kqueue]: https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 is_aio(&self) -> bool163 pub fn is_aio(&self) -> bool { 164 sys::event::is_aio(&self.inner) 165 } 166 167 /// Returns true if the event contains LIO readiness. 168 /// 169 /// # Notes 170 /// 171 /// Method is available on all platforms, but only FreeBSD supports LIO. On 172 /// FreeBSD this method checks the `EVFILT_LIO` flag. is_lio(&self) -> bool173 pub fn is_lio(&self) -> bool { 174 sys::event::is_lio(&self.inner) 175 } 176 177 /// Create a reference to an `Event` from a platform specific event. from_sys_event_ref(sys_event: &sys::Event) -> &Event178 pub(crate) fn from_sys_event_ref(sys_event: &sys::Event) -> &Event { 179 unsafe { 180 // This is safe because the memory layout of `Event` is 181 // the same as `sys::Event` due to the `repr(transparent)` attribute. 182 &*(sys_event as *const sys::Event as *const Event) 183 } 184 } 185 } 186 187 /// When the [alternate] flag is enabled this will print platform specific 188 /// details, for example the fields of the `kevent` structure on platforms that 189 /// use `kqueue(2)`. Note however that the output of this implementation is 190 /// **not** consider a part of the stable API. 191 /// 192 /// [alternate]: fmt::Formatter::alternate 193 impl fmt::Debug for Event { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 195 let alternate = f.alternate(); 196 let mut d = f.debug_struct("Event"); 197 d.field("token", &self.token()) 198 .field("readable", &self.is_readable()) 199 .field("writable", &self.is_writable()) 200 .field("error", &self.is_error()) 201 .field("read_closed", &self.is_read_closed()) 202 .field("write_closed", &self.is_write_closed()) 203 .field("priority", &self.is_priority()) 204 .field("aio", &self.is_aio()) 205 .field("lio", &self.is_lio()); 206 207 if alternate { 208 struct EventDetails<'a>(&'a sys::Event); 209 210 impl<'a> fmt::Debug for EventDetails<'a> { 211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 212 sys::event::debug_details(f, self.0) 213 } 214 } 215 216 d.field("details", &EventDetails(&self.inner)).finish() 217 } else { 218 d.finish() 219 } 220 } 221 } 222