1
1
//! Wait for events to trigger on specific file descriptors
2
+ use std:: convert:: TryFrom ;
2
3
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
4
+ use std:: time:: Duration ;
3
5
4
6
use crate :: errno:: Errno ;
5
7
use crate :: Result ;
6
-
7
8
/// This is a wrapper around `libc::pollfd`.
8
9
///
9
10
/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
@@ -132,6 +133,179 @@ libc_bitflags! {
132
133
}
133
134
}
134
135
136
+ /// Timeout argument for [`poll`].
137
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq , Ord , PartialOrd ) ]
138
+ pub struct PollTimeout ( i32 ) ;
139
+
140
+ impl PollTimeout {
141
+ /// Blocks indefinitely.
142
+ ///
143
+ /// > Specifying a negative value in timeout means an infinite timeout.
144
+ pub const NONE : Self = Self ( -1 ) ;
145
+ /// Returns immediately.
146
+ ///
147
+ /// > Specifying a timeout of zero causes poll() to return immediately, even if no file
148
+ /// > descriptors are ready.
149
+ pub const ZERO : Self = Self ( 0 ) ;
150
+ /// Blocks for at most [`std::i32::MAX`] milliseconds.
151
+ pub const MAX : Self = Self ( i32:: MAX ) ;
152
+ /// Returns if `self` equals [`PollTimeout::NONE`].
153
+ pub fn is_none ( & self ) -> bool {
154
+ // > Specifying a negative value in timeout means an infinite timeout.
155
+ * self <= Self :: NONE
156
+ }
157
+ /// Returns if `self` does not equal [`PollTimeout::NONE`].
158
+ pub fn is_some ( & self ) -> bool {
159
+ !self . is_none ( )
160
+ }
161
+ /// Returns the timeout in milliseconds if there is some, otherwise returns `None`.
162
+ pub fn timeout ( & self ) -> Option < i32 > {
163
+ self . is_some ( ) . then_some ( self . 0 )
164
+ }
165
+ }
166
+
167
+ impl TryFrom < Duration > for PollTimeout {
168
+ type Error = <i32 as TryFrom < u128 > >:: Error ;
169
+ fn try_from ( x : Duration ) -> std:: result:: Result < Self , Self :: Error > {
170
+ Ok ( Self ( i32:: try_from ( x. as_millis ( ) ) ?) )
171
+ }
172
+ }
173
+ impl TryFrom < u128 > for PollTimeout {
174
+ type Error = <i32 as TryFrom < u128 > >:: Error ;
175
+ fn try_from ( x : u128 ) -> std:: result:: Result < Self , Self :: Error > {
176
+ Ok ( Self ( i32:: try_from ( x) ?) )
177
+ }
178
+ }
179
+ impl TryFrom < u64 > for PollTimeout {
180
+ type Error = <i32 as TryFrom < u64 > >:: Error ;
181
+ fn try_from ( x : u64 ) -> std:: result:: Result < Self , Self :: Error > {
182
+ Ok ( Self ( i32:: try_from ( x) ?) )
183
+ }
184
+ }
185
+ impl TryFrom < u32 > for PollTimeout {
186
+ type Error = <i32 as TryFrom < u32 > >:: Error ;
187
+ fn try_from ( x : u32 ) -> std:: result:: Result < Self , Self :: Error > {
188
+ Ok ( Self ( i32:: try_from ( x) ?) )
189
+ }
190
+ }
191
+ impl From < u16 > for PollTimeout {
192
+ fn from ( x : u16 ) -> Self {
193
+ Self ( i32:: from ( x) )
194
+ }
195
+ }
196
+ impl From < u8 > for PollTimeout {
197
+ fn from ( x : u8 ) -> Self {
198
+ Self ( i32:: from ( x) )
199
+ }
200
+ }
201
+ impl TryFrom < i128 > for PollTimeout {
202
+ type Error = <i32 as TryFrom < i128 > >:: Error ;
203
+ fn try_from ( x : i128 ) -> std:: result:: Result < Self , Self :: Error > {
204
+ match x {
205
+ // > Specifying a negative value in timeout means an infinite timeout.
206
+ i128:: MIN ..=-1 => Ok ( Self :: NONE ) ,
207
+ millis @ 0 .. => Ok ( Self (
208
+ i32:: try_from ( millis) ?,
209
+ ) ) ,
210
+ }
211
+ }
212
+ }
213
+ impl TryFrom < i64 > for PollTimeout {
214
+ type Error = <i32 as TryFrom < i64 > >:: Error ;
215
+ fn try_from ( x : i64 ) -> std:: result:: Result < Self , Self :: Error > {
216
+ match x {
217
+ i64:: MIN ..=-1 => Ok ( Self :: NONE ) ,
218
+ millis @ 0 .. => Ok ( Self (
219
+ i32:: try_from ( millis) ?,
220
+ ) ) ,
221
+ }
222
+ }
223
+ }
224
+ impl From < i32 > for PollTimeout {
225
+ fn from ( x : i32 ) -> Self {
226
+ Self ( x)
227
+ }
228
+ }
229
+ impl From < i16 > for PollTimeout {
230
+ fn from ( x : i16 ) -> Self {
231
+ Self ( i32:: from ( x) )
232
+ }
233
+ }
234
+ impl From < i8 > for PollTimeout {
235
+ fn from ( x : i8 ) -> Self {
236
+ Self ( i32:: from ( x) )
237
+ }
238
+ }
239
+ impl TryFrom < PollTimeout > for Duration {
240
+ type Error = ( ) ;
241
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , ( ) > {
242
+ match x. timeout ( ) {
243
+ // SAFETY: When `x.timeout()` returns `Some(a)`, `a` is always non-negative.
244
+ Some ( millis) => Ok ( Duration :: from_millis ( unsafe {
245
+ u64:: try_from ( millis) . unwrap_unchecked ( )
246
+ } ) ) ,
247
+ None => Err ( ( ) ) ,
248
+ }
249
+ }
250
+ }
251
+ impl TryFrom < PollTimeout > for u128 {
252
+ type Error = <Self as TryFrom < i32 > >:: Error ;
253
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
254
+ Self :: try_from ( x. 0 )
255
+ }
256
+ }
257
+ impl TryFrom < PollTimeout > for u64 {
258
+ type Error = <Self as TryFrom < i32 > >:: Error ;
259
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
260
+ Self :: try_from ( x. 0 )
261
+ }
262
+ }
263
+ impl TryFrom < PollTimeout > for u32 {
264
+ type Error = <Self as TryFrom < i32 > >:: Error ;
265
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
266
+ Self :: try_from ( x. 0 )
267
+ }
268
+ }
269
+ impl TryFrom < PollTimeout > for u16 {
270
+ type Error = <Self as TryFrom < i32 > >:: Error ;
271
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
272
+ Self :: try_from ( x. 0 )
273
+ }
274
+ }
275
+ impl TryFrom < PollTimeout > for u8 {
276
+ type Error = <Self as TryFrom < i32 > >:: Error ;
277
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
278
+ Self :: try_from ( x. 0 )
279
+ }
280
+ }
281
+ impl From < PollTimeout > for i128 {
282
+ fn from ( x : PollTimeout ) -> Self {
283
+ Self :: from ( x. 0 )
284
+ }
285
+ }
286
+ impl From < PollTimeout > for i64 {
287
+ fn from ( x : PollTimeout ) -> Self {
288
+ Self :: from ( x. 0 )
289
+ }
290
+ }
291
+ impl From < PollTimeout > for i32 {
292
+ fn from ( x : PollTimeout ) -> Self {
293
+ x. 0
294
+ }
295
+ }
296
+ impl TryFrom < PollTimeout > for i16 {
297
+ type Error = <Self as TryFrom < i32 > >:: Error ;
298
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
299
+ Self :: try_from ( x. 0 )
300
+ }
301
+ }
302
+ impl TryFrom < PollTimeout > for i8 {
303
+ type Error = <Self as TryFrom < i32 > >:: Error ;
304
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
305
+ Self :: try_from ( x. 0 )
306
+ }
307
+ }
308
+
135
309
/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
136
310
/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
137
311
///
@@ -148,16 +322,16 @@ libc_bitflags! {
148
322
///
149
323
/// Note that the timeout interval will be rounded up to the system clock
150
324
/// granularity, and kernel scheduling delays mean that the blocking
151
- /// interval may overrun by a small amount. Specifying a negative value
152
- /// in timeout means an infinite timeout. Specifying a timeout of zero
153
- /// causes `poll()` to return immediately, even if no file descriptors are
154
- /// ready.
155
- pub fn poll ( fds : & mut [ PollFd ] , timeout : libc :: c_int ) -> Result < libc:: c_int > {
325
+ /// interval may overrun by a small amount. Specifying a [`PollTimeout::NONE`]
326
+ /// in timeout means an infinite timeout. Specifying a timeout of
327
+ /// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file
328
+ /// descriptors are ready.
329
+ pub fn poll < T : Into < PollTimeout > > ( fds : & mut [ PollFd ] , timeout : T ) -> Result < libc:: c_int > {
156
330
let res = unsafe {
157
331
libc:: poll (
158
332
fds. as_mut_ptr ( ) as * mut libc:: pollfd ,
159
333
fds. len ( ) as libc:: nfds_t ,
160
- timeout,
334
+ i32 :: from ( timeout. into ( ) ) ,
161
335
)
162
336
} ;
163
337
0 commit comments