1 #![cfg_attr(not(feature = "net"), allow(unreachable_pub))] 2 3 use std::fmt; 4 use std::ops; 5 6 const READABLE: usize = 0b0_01; 7 const WRITABLE: usize = 0b0_10; 8 const READ_CLOSED: usize = 0b0_0100; 9 const WRITE_CLOSED: usize = 0b0_1000; 10 11 /// Describes the readiness state of an I/O resources. 12 /// 13 /// `Ready` tracks which operation an I/O resource is ready to perform. 14 #[cfg_attr(docsrs, doc(cfg(feature = "net")))] 15 #[derive(Clone, Copy, PartialEq, PartialOrd)] 16 pub struct Ready(usize); 17 18 impl Ready { 19 /// Returns the empty `Ready` set. 20 pub const EMPTY: Ready = Ready(0); 21 22 /// Returns a `Ready` representing readable readiness. 23 pub const READABLE: Ready = Ready(READABLE); 24 25 /// Returns a `Ready` representing writable readiness. 26 pub const WRITABLE: Ready = Ready(WRITABLE); 27 28 /// Returns a `Ready` representing read closed readiness. 29 pub const READ_CLOSED: Ready = Ready(READ_CLOSED); 30 31 /// Returns a `Ready` representing write closed readiness. 32 pub const WRITE_CLOSED: Ready = Ready(WRITE_CLOSED); 33 34 /// Returns a `Ready` representing readiness for all operations. 35 pub const ALL: Ready = Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED); 36 37 // Must remain crate-private to avoid adding a public dependency on Mio. from_mio(event: &mio::event::Event) -> Ready38 pub(crate) fn from_mio(event: &mio::event::Event) -> Ready { 39 let mut ready = Ready::EMPTY; 40 41 #[cfg(all(target_os = "freebsd", feature = "net"))] 42 { 43 if event.is_aio() { 44 ready |= Ready::READABLE; 45 } 46 47 if event.is_lio() { 48 ready |= Ready::READABLE; 49 } 50 } 51 52 if event.is_readable() { 53 ready |= Ready::READABLE; 54 } 55 56 if event.is_writable() { 57 ready |= Ready::WRITABLE; 58 } 59 60 if event.is_read_closed() { 61 ready |= Ready::READ_CLOSED; 62 } 63 64 if event.is_write_closed() { 65 ready |= Ready::WRITE_CLOSED; 66 } 67 68 ready 69 } 70 71 /// Returns true if `Ready` is the empty set. 72 /// 73 /// # Examples 74 /// 75 /// ``` 76 /// use tokio::io::Ready; 77 /// 78 /// assert!(Ready::EMPTY.is_empty()); 79 /// assert!(!Ready::READABLE.is_empty()); 80 /// ``` is_empty(self) -> bool81 pub fn is_empty(self) -> bool { 82 self == Ready::EMPTY 83 } 84 85 /// Returns `true` if the value includes `readable`. 86 /// 87 /// # Examples 88 /// 89 /// ``` 90 /// use tokio::io::Ready; 91 /// 92 /// assert!(!Ready::EMPTY.is_readable()); 93 /// assert!(Ready::READABLE.is_readable()); 94 /// assert!(Ready::READ_CLOSED.is_readable()); 95 /// assert!(!Ready::WRITABLE.is_readable()); 96 /// ``` is_readable(self) -> bool97 pub fn is_readable(self) -> bool { 98 self.contains(Ready::READABLE) || self.is_read_closed() 99 } 100 101 /// Returns `true` if the value includes writable `readiness`. 102 /// 103 /// # Examples 104 /// 105 /// ``` 106 /// use tokio::io::Ready; 107 /// 108 /// assert!(!Ready::EMPTY.is_writable()); 109 /// assert!(!Ready::READABLE.is_writable()); 110 /// assert!(Ready::WRITABLE.is_writable()); 111 /// assert!(Ready::WRITE_CLOSED.is_writable()); 112 /// ``` is_writable(self) -> bool113 pub fn is_writable(self) -> bool { 114 self.contains(Ready::WRITABLE) || self.is_write_closed() 115 } 116 117 /// Returns `true` if the value includes read-closed `readiness`. 118 /// 119 /// # Examples 120 /// 121 /// ``` 122 /// use tokio::io::Ready; 123 /// 124 /// assert!(!Ready::EMPTY.is_read_closed()); 125 /// assert!(!Ready::READABLE.is_read_closed()); 126 /// assert!(Ready::READ_CLOSED.is_read_closed()); 127 /// ``` is_read_closed(self) -> bool128 pub fn is_read_closed(self) -> bool { 129 self.contains(Ready::READ_CLOSED) 130 } 131 132 /// Returns `true` if the value includes write-closed `readiness`. 133 /// 134 /// # Examples 135 /// 136 /// ``` 137 /// use tokio::io::Ready; 138 /// 139 /// assert!(!Ready::EMPTY.is_write_closed()); 140 /// assert!(!Ready::WRITABLE.is_write_closed()); 141 /// assert!(Ready::WRITE_CLOSED.is_write_closed()); 142 /// ``` is_write_closed(self) -> bool143 pub fn is_write_closed(self) -> bool { 144 self.contains(Ready::WRITE_CLOSED) 145 } 146 147 /// Returns true if `self` is a superset of `other`. 148 /// 149 /// `other` may represent more than one readiness operations, in which case 150 /// the function only returns true if `self` contains all readiness 151 /// specified in `other`. contains<T: Into<Self>>(self, other: T) -> bool152 pub(crate) fn contains<T: Into<Self>>(self, other: T) -> bool { 153 let other = other.into(); 154 (self & other) == other 155 } 156 157 /// Creates a `Ready` instance using the given `usize` representation. 158 /// 159 /// The `usize` representation must have been obtained from a call to 160 /// `Readiness::as_usize`. 161 /// 162 /// This function is mainly provided to allow the caller to get a 163 /// readiness value from an `AtomicUsize`. from_usize(val: usize) -> Ready164 pub(crate) fn from_usize(val: usize) -> Ready { 165 Ready(val & Ready::ALL.as_usize()) 166 } 167 168 /// Returns a `usize` representation of the `Ready` value. 169 /// 170 /// This function is mainly provided to allow the caller to store a 171 /// readiness value in an `AtomicUsize`. as_usize(self) -> usize172 pub(crate) fn as_usize(self) -> usize { 173 self.0 174 } 175 } 176 177 cfg_io_readiness! { 178 use crate::io::Interest; 179 180 impl Ready { 181 pub(crate) fn from_interest(interest: Interest) -> Ready { 182 let mut ready = Ready::EMPTY; 183 184 if interest.is_readable() { 185 ready |= Ready::READABLE; 186 ready |= Ready::READ_CLOSED; 187 } 188 189 if interest.is_writable() { 190 ready |= Ready::WRITABLE; 191 ready |= Ready::WRITE_CLOSED; 192 } 193 194 ready 195 } 196 197 pub(crate) fn intersection(self, interest: Interest) -> Ready { 198 Ready(self.0 & Ready::from_interest(interest).0) 199 } 200 201 pub(crate) fn satisfies(self, interest: Interest) -> bool { 202 self.0 & Ready::from_interest(interest).0 != 0 203 } 204 } 205 } 206 207 impl ops::BitOr<Ready> for Ready { 208 type Output = Ready; 209 210 #[inline] bitor(self, other: Ready) -> Ready211 fn bitor(self, other: Ready) -> Ready { 212 Ready(self.0 | other.0) 213 } 214 } 215 216 impl ops::BitOrAssign<Ready> for Ready { 217 #[inline] bitor_assign(&mut self, other: Ready)218 fn bitor_assign(&mut self, other: Ready) { 219 self.0 |= other.0; 220 } 221 } 222 223 impl ops::BitAnd<Ready> for Ready { 224 type Output = Ready; 225 226 #[inline] bitand(self, other: Ready) -> Ready227 fn bitand(self, other: Ready) -> Ready { 228 Ready(self.0 & other.0) 229 } 230 } 231 232 impl ops::Sub<Ready> for Ready { 233 type Output = Ready; 234 235 #[inline] sub(self, other: Ready) -> Ready236 fn sub(self, other: Ready) -> Ready { 237 Ready(self.0 & !other.0) 238 } 239 } 240 241 impl fmt::Debug for Ready { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result242 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 243 fmt.debug_struct("Ready") 244 .field("is_readable", &self.is_readable()) 245 .field("is_writable", &self.is_writable()) 246 .field("is_read_closed", &self.is_read_closed()) 247 .field("is_write_closed", &self.is_write_closed()) 248 .finish() 249 } 250 } 251