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 if event.is_readable() { 42 ready |= Ready::READABLE; 43 } 44 45 if event.is_writable() { 46 ready |= Ready::WRITABLE; 47 } 48 49 if event.is_read_closed() { 50 ready |= Ready::READ_CLOSED; 51 } 52 53 if event.is_write_closed() { 54 ready |= Ready::WRITE_CLOSED; 55 } 56 57 ready 58 } 59 60 /// Returns true if `Ready` is the empty set 61 /// 62 /// # Examples 63 /// 64 /// ``` 65 /// use tokio::io::Ready; 66 /// 67 /// assert!(Ready::EMPTY.is_empty()); 68 /// assert!(!Ready::READABLE.is_empty()); 69 /// ``` is_empty(self) -> bool70 pub fn is_empty(self) -> bool { 71 self == Ready::EMPTY 72 } 73 74 /// Returns `true` if the value includes `readable` 75 /// 76 /// # Examples 77 /// 78 /// ``` 79 /// use tokio::io::Ready; 80 /// 81 /// assert!(!Ready::EMPTY.is_readable()); 82 /// assert!(Ready::READABLE.is_readable()); 83 /// assert!(Ready::READ_CLOSED.is_readable()); 84 /// assert!(!Ready::WRITABLE.is_readable()); 85 /// ``` is_readable(self) -> bool86 pub fn is_readable(self) -> bool { 87 self.contains(Ready::READABLE) || self.is_read_closed() 88 } 89 90 /// Returns `true` if the value includes writable `readiness` 91 /// 92 /// # Examples 93 /// 94 /// ``` 95 /// use tokio::io::Ready; 96 /// 97 /// assert!(!Ready::EMPTY.is_writable()); 98 /// assert!(!Ready::READABLE.is_writable()); 99 /// assert!(Ready::WRITABLE.is_writable()); 100 /// assert!(Ready::WRITE_CLOSED.is_writable()); 101 /// ``` is_writable(self) -> bool102 pub fn is_writable(self) -> bool { 103 self.contains(Ready::WRITABLE) || self.is_write_closed() 104 } 105 106 /// Returns `true` if the value includes read-closed `readiness` 107 /// 108 /// # Examples 109 /// 110 /// ``` 111 /// use tokio::io::Ready; 112 /// 113 /// assert!(!Ready::EMPTY.is_read_closed()); 114 /// assert!(!Ready::READABLE.is_read_closed()); 115 /// assert!(Ready::READ_CLOSED.is_read_closed()); 116 /// ``` is_read_closed(self) -> bool117 pub fn is_read_closed(self) -> bool { 118 self.contains(Ready::READ_CLOSED) 119 } 120 121 /// Returns `true` if the value includes write-closed `readiness` 122 /// 123 /// # Examples 124 /// 125 /// ``` 126 /// use tokio::io::Ready; 127 /// 128 /// assert!(!Ready::EMPTY.is_write_closed()); 129 /// assert!(!Ready::WRITABLE.is_write_closed()); 130 /// assert!(Ready::WRITE_CLOSED.is_write_closed()); 131 /// ``` is_write_closed(self) -> bool132 pub fn is_write_closed(self) -> bool { 133 self.contains(Ready::WRITE_CLOSED) 134 } 135 136 /// Returns true if `self` is a superset of `other`. 137 /// 138 /// `other` may represent more than one readiness operations, in which case 139 /// the function only returns true if `self` contains all readiness 140 /// specified in `other`. contains<T: Into<Self>>(self, other: T) -> bool141 pub(crate) fn contains<T: Into<Self>>(self, other: T) -> bool { 142 let other = other.into(); 143 (self & other) == other 144 } 145 146 /// Create a `Ready` instance using the given `usize` representation. 147 /// 148 /// The `usize` representation must have been obtained from a call to 149 /// `Readiness::as_usize`. 150 /// 151 /// This function is mainly provided to allow the caller to get a 152 /// readiness value from an `AtomicUsize`. from_usize(val: usize) -> Ready153 pub(crate) fn from_usize(val: usize) -> Ready { 154 Ready(val & Ready::ALL.as_usize()) 155 } 156 157 /// Returns a `usize` representation of the `Ready` value. 158 /// 159 /// This function is mainly provided to allow the caller to store a 160 /// readiness value in an `AtomicUsize`. as_usize(self) -> usize161 pub(crate) fn as_usize(self) -> usize { 162 self.0 163 } 164 } 165 166 cfg_io_readiness! { 167 use crate::io::Interest; 168 169 impl Ready { 170 pub(crate) fn from_interest(interest: Interest) -> Ready { 171 let mut ready = Ready::EMPTY; 172 173 if interest.is_readable() { 174 ready |= Ready::READABLE; 175 ready |= Ready::READ_CLOSED; 176 } 177 178 if interest.is_writable() { 179 ready |= Ready::WRITABLE; 180 ready |= Ready::WRITE_CLOSED; 181 } 182 183 ready 184 } 185 186 pub(crate) fn intersection(self, interest: Interest) -> Ready { 187 Ready(self.0 & Ready::from_interest(interest).0) 188 } 189 190 pub(crate) fn satisfies(self, interest: Interest) -> bool { 191 self.0 & Ready::from_interest(interest).0 != 0 192 } 193 } 194 } 195 196 impl ops::BitOr<Ready> for Ready { 197 type Output = Ready; 198 199 #[inline] bitor(self, other: Ready) -> Ready200 fn bitor(self, other: Ready) -> Ready { 201 Ready(self.0 | other.0) 202 } 203 } 204 205 impl ops::BitOrAssign<Ready> for Ready { 206 #[inline] bitor_assign(&mut self, other: Ready)207 fn bitor_assign(&mut self, other: Ready) { 208 self.0 |= other.0; 209 } 210 } 211 212 impl ops::BitAnd<Ready> for Ready { 213 type Output = Ready; 214 215 #[inline] bitand(self, other: Ready) -> Ready216 fn bitand(self, other: Ready) -> Ready { 217 Ready(self.0 & other.0) 218 } 219 } 220 221 impl ops::Sub<Ready> for Ready { 222 type Output = Ready; 223 224 #[inline] sub(self, other: Ready) -> Ready225 fn sub(self, other: Ready) -> Ready { 226 Ready(self.0 & !other.0) 227 } 228 } 229 230 impl fmt::Debug for Ready { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result231 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 232 fmt.debug_struct("Ready") 233 .field("is_readable", &self.is_readable()) 234 .field("is_writable", &self.is_writable()) 235 .field("is_read_closed", &self.is_read_closed()) 236 .field("is_write_closed", &self.is_write_closed()) 237 .finish() 238 } 239 } 240