@@ -5,49 +5,70 @@ use crate::io::ready::Ready;
5
5
use std:: fmt;
6
6
use std:: ops;
7
7
8
+ // These must be unique.
9
+ // same as mio
10
+ const READABLE : usize = 0b0001 ;
11
+ const WRITABLE : usize = 0b0010 ;
12
+ // The following are not available on all platforms.
13
+ #[ cfg( target_os = "freebsd" ) ]
14
+ const AIO : usize = 0b0100 ;
15
+ #[ cfg( target_os = "freebsd" ) ]
16
+ const LIO : usize = 0b1000 ;
17
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
18
+ const PRIORITY : usize = 0b0001_0000 ;
19
+ // error is available on all platforms, but behavior is platform-specific
20
+ // mio does not have this interest
21
+ const ERROR : usize = 0b0010_0000 ;
22
+
8
23
/// Readiness event interest.
9
24
///
10
25
/// Specifies the readiness events the caller is interested in when awaiting on
11
26
/// I/O resource readiness states.
12
27
#[ cfg_attr( docsrs, doc( cfg( feature = "net" ) ) ) ]
13
28
#[ derive( Clone , Copy , Eq , PartialEq ) ]
14
- pub struct Interest ( mio :: Interest ) ;
29
+ pub struct Interest ( usize ) ;
15
30
16
31
impl Interest {
17
32
// The non-FreeBSD definitions in this block are active only when
18
33
// building documentation.
19
34
cfg_aio ! {
20
35
/// Interest for POSIX AIO.
21
36
#[ cfg( target_os = "freebsd" ) ]
22
- pub const AIO : Interest = Interest ( mio :: Interest :: AIO ) ;
37
+ pub const AIO : Interest = Interest ( AIO ) ;
23
38
24
39
/// Interest for POSIX AIO.
25
40
#[ cfg( not( target_os = "freebsd" ) ) ]
26
- pub const AIO : Interest = Interest ( mio :: Interest :: READABLE ) ;
41
+ pub const AIO : Interest = Interest ( READABLE ) ;
27
42
28
43
/// Interest for POSIX AIO lio_listio events.
29
44
#[ cfg( target_os = "freebsd" ) ]
30
- pub const LIO : Interest = Interest ( mio :: Interest :: LIO ) ;
45
+ pub const LIO : Interest = Interest ( LIO ) ;
31
46
32
47
/// Interest for POSIX AIO lio_listio events.
33
48
#[ cfg( not( target_os = "freebsd" ) ) ]
34
- pub const LIO : Interest = Interest ( mio :: Interest :: READABLE ) ;
49
+ pub const LIO : Interest = Interest ( READABLE ) ;
35
50
}
36
51
37
52
/// Interest in all readable events.
38
53
///
39
54
/// Readable interest includes read-closed events.
40
- pub const READABLE : Interest = Interest ( mio :: Interest :: READABLE ) ;
55
+ pub const READABLE : Interest = Interest ( READABLE ) ;
41
56
42
57
/// Interest in all writable events.
43
58
///
44
59
/// Writable interest includes write-closed events.
45
- pub const WRITABLE : Interest = Interest ( mio:: Interest :: WRITABLE ) ;
60
+ pub const WRITABLE : Interest = Interest ( WRITABLE ) ;
61
+
62
+ /// Interest in error events.
63
+ ///
64
+ /// Passes error interest to the underlying OS selector.
65
+ /// Behavior is platform-specific, read your platform's documentation.
66
+ pub const ERROR : Interest = Interest ( ERROR ) ;
46
67
47
68
/// Returns a `Interest` set representing priority completion interests.
48
69
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
49
70
#[ cfg_attr( docsrs, doc( cfg( any( target_os = "linux" , target_os = "android" ) ) ) ) ]
50
- pub const PRIORITY : Interest = Interest ( mio :: Interest :: PRIORITY ) ;
71
+ pub const PRIORITY : Interest = Interest ( PRIORITY ) ;
51
72
52
73
/// Returns true if the value includes readable interest.
53
74
///
@@ -63,7 +84,7 @@ impl Interest {
63
84
/// assert!(both.is_readable());
64
85
/// ```
65
86
pub const fn is_readable ( self ) -> bool {
66
- self . 0 . is_readable ( )
87
+ self . 0 & READABLE != 0
67
88
}
68
89
69
90
/// Returns true if the value includes writable interest.
@@ -80,7 +101,34 @@ impl Interest {
80
101
/// assert!(both.is_writable());
81
102
/// ```
82
103
pub const fn is_writable ( self ) -> bool {
83
- self . 0 . is_writable ( )
104
+ self . 0 & WRITABLE != 0
105
+ }
106
+
107
+ /// Returns true if the value includes error interest.
108
+ ///
109
+ /// # Examples
110
+ ///
111
+ /// ```
112
+ /// use tokio::io::Interest;
113
+ ///
114
+ /// assert!(Interest::ERROR.is_error());
115
+ /// assert!(!Interest::WRITABLE.is_error());
116
+ ///
117
+ /// let combined = Interest::READABLE | Interest::ERROR;
118
+ /// assert!(combined.is_error());
119
+ /// ```
120
+ pub const fn is_error ( self ) -> bool {
121
+ self . 0 & ERROR != 0
122
+ }
123
+
124
+ #[ cfg( target_os = "freebsd" ) ]
125
+ const fn is_aio ( self ) -> bool {
126
+ self . 0 & AIO != 0
127
+ }
128
+
129
+ #[ cfg( target_os = "freebsd" ) ]
130
+ const fn is_lio ( self ) -> bool {
131
+ self . 0 & LIO != 0
84
132
}
85
133
86
134
/// Returns true if the value includes priority interest.
@@ -99,7 +147,7 @@ impl Interest {
99
147
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
100
148
#[ cfg_attr( docsrs, doc( cfg( any( target_os = "linux" , target_os = "android" ) ) ) ) ]
101
149
pub const fn is_priority ( self ) -> bool {
102
- self . 0 . is_priority ( )
150
+ self . 0 & PRIORITY != 0
103
151
}
104
152
105
153
/// Add together two `Interest` values.
@@ -116,12 +164,60 @@ impl Interest {
116
164
/// assert!(BOTH.is_readable());
117
165
/// assert!(BOTH.is_writable());
118
166
pub const fn add ( self , other : Interest ) -> Interest {
119
- Interest ( self . 0 . add ( other. 0 ) )
167
+ Self ( self . 0 | other. 0 )
120
168
}
121
169
122
170
// This function must be crate-private to avoid exposing a `mio` dependency.
123
- pub ( crate ) const fn to_mio ( self ) -> mio:: Interest {
124
- self . 0
171
+ pub ( crate ) fn to_mio ( self ) -> mio:: Interest {
172
+ fn mio_add ( wrapped : & mut Option < mio:: Interest > , add : mio:: Interest ) {
173
+ match wrapped {
174
+ Some ( inner) => * inner |= add,
175
+ None => * wrapped = Some ( add) ,
176
+ }
177
+ }
178
+
179
+ // mio does not allow and empty interest, so use None for empty
180
+ let mut mio = None ;
181
+
182
+ if self . is_readable ( ) {
183
+ mio_add ( & mut mio, mio:: Interest :: READABLE ) ;
184
+ }
185
+
186
+ if self . is_writable ( ) {
187
+ mio_add ( & mut mio, mio:: Interest :: WRITABLE ) ;
188
+ }
189
+
190
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
191
+ if self . is_priority ( ) {
192
+ mio_add ( & mut mio, mio:: Interest :: PRIORITY ) ;
193
+ }
194
+
195
+ #[ cfg( target_os = "freebsd" ) ]
196
+ if self . is_aio ( ) {
197
+ mio_add ( & mut mio, mio:: Interest :: AIO ) ;
198
+ }
199
+
200
+ #[ cfg( target_os = "freebsd" ) ]
201
+ if self . is_lio ( ) {
202
+ mio_add ( & mut mio, mio:: Interest :: LIO ) ;
203
+ }
204
+
205
+ if self . is_error ( ) {
206
+ // There is no error interest in mio, because error events are always reported.
207
+ // But mio interests cannot be empty and an interest is needed just for the registeration.
208
+ //
209
+ // read readiness is filtered out in `Interest::mask` or `Ready::from_interest` if
210
+ // the read interest was not specified by the user.
211
+ mio_add ( & mut mio, mio:: Interest :: READABLE ) ;
212
+ }
213
+
214
+ // the default `mio::Interest::READABLE` should never be used in practice. Either
215
+ //
216
+ // - at least one tokio interest with a mio counterpart was used
217
+ // - only the error tokio interest was specified
218
+ //
219
+ // in both cases, `mio` is Some already
220
+ mio. unwrap_or ( mio:: Interest :: READABLE )
125
221
}
126
222
127
223
pub ( crate ) fn mask ( self ) -> Ready {
@@ -130,6 +226,7 @@ impl Interest {
130
226
Interest :: WRITABLE => Ready :: WRITABLE | Ready :: WRITE_CLOSED ,
131
227
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
132
228
Interest :: PRIORITY => Ready :: PRIORITY | Ready :: READ_CLOSED ,
229
+ Interest :: ERROR => Ready :: ERROR ,
133
230
_ => Ready :: EMPTY ,
134
231
}
135
232
}
@@ -147,12 +244,67 @@ impl ops::BitOr for Interest {
147
244
impl ops:: BitOrAssign for Interest {
148
245
#[ inline]
149
246
fn bitor_assign ( & mut self , other : Self ) {
150
- self . 0 = ( * self | other) . 0 ;
247
+ * self = * self | other
151
248
}
152
249
}
153
250
154
251
impl fmt:: Debug for Interest {
155
252
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
156
- self . 0 . fmt ( fmt)
253
+ let mut separator = false ;
254
+
255
+ if self . is_readable ( ) {
256
+ if separator {
257
+ write ! ( fmt, " | " ) ?;
258
+ }
259
+ write ! ( fmt, "READABLE" ) ?;
260
+ separator = true ;
261
+ }
262
+
263
+ if self . is_writable ( ) {
264
+ if separator {
265
+ write ! ( fmt, " | " ) ?;
266
+ }
267
+ write ! ( fmt, "WRITABLE" ) ?;
268
+ separator = true ;
269
+ }
270
+
271
+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
272
+ if self . is_priority ( ) {
273
+ if separator {
274
+ write ! ( fmt, " | " ) ?;
275
+ }
276
+ write ! ( fmt, "PRIORITY" ) ?;
277
+ separator = true ;
278
+ }
279
+
280
+ #[ cfg( target_os = "freebsd" ) ]
281
+ if self . is_aio ( ) {
282
+ if separator {
283
+ write ! ( fmt, " | " ) ?;
284
+ }
285
+ write ! ( fmt, "AIO" ) ?;
286
+ separator = true ;
287
+ }
288
+
289
+ #[ cfg( target_os = "freebsd" ) ]
290
+ if self . is_lio ( ) {
291
+ if separator {
292
+ write ! ( fmt, " | " ) ?;
293
+ }
294
+ write ! ( fmt, "LIO" ) ?;
295
+ separator = true ;
296
+ }
297
+
298
+ if self . is_error ( ) {
299
+ if separator {
300
+ write ! ( fmt, " | " ) ?;
301
+ }
302
+ write ! ( fmt, "ERROR" ) ?;
303
+ separator = true ;
304
+ }
305
+
306
+ let _ = separator;
307
+
308
+ Ok ( ( ) )
157
309
}
158
310
}
0 commit comments