• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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