1
1
//! Wait for events to trigger on specific file descriptors
2
2
use std:: os:: unix:: io:: { AsFd , AsRawFd , BorrowedFd } ;
3
+ use std:: time:: Duration ;
3
4
4
5
use crate :: errno:: Errno ;
5
6
use crate :: Result ;
6
-
7
7
/// This is a wrapper around `libc::pollfd`.
8
8
///
9
9
/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
@@ -27,13 +27,13 @@ impl<'fd> PollFd<'fd> {
27
27
/// ```no_run
28
28
/// # use std::os::unix::io::{AsFd, AsRawFd, FromRawFd};
29
29
/// # use nix::{
30
- /// # poll::{PollFd, PollFlags, poll},
30
+ /// # poll::{PollTimeout, PollFd, PollFlags, poll},
31
31
/// # unistd::{pipe, read}
32
32
/// # };
33
33
/// let (r, w) = pipe().unwrap();
34
34
/// let pfd = PollFd::new(r.as_fd(), PollFlags::POLLIN);
35
35
/// let mut fds = [pfd];
36
- /// poll(&mut fds, -1 ).unwrap();
36
+ /// poll(&mut fds, PollTimeout::NONE ).unwrap();
37
37
/// let mut buf = [0u8; 80];
38
38
/// read(r.as_raw_fd(), &mut buf[..]);
39
39
/// ```
@@ -179,6 +179,210 @@ libc_bitflags! {
179
179
}
180
180
}
181
181
182
+ /// Timeout argument for [`poll`].
183
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq , Ord , PartialOrd ) ]
184
+ pub struct PollTimeout ( i32 ) ;
185
+
186
+ impl PollTimeout {
187
+ /// Blocks indefinitely.
188
+ ///
189
+ /// > Specifying a negative value in timeout means an infinite timeout.
190
+ pub const NONE : Self = Self ( -1 ) ;
191
+ /// Returns immediately.
192
+ ///
193
+ /// > Specifying a timeout of zero causes poll() to return immediately, even if no file
194
+ /// > descriptors are ready.
195
+ pub const ZERO : Self = Self ( 0 ) ;
196
+ /// Blocks for at most [`std::i32::MAX`] milliseconds.
197
+ pub const MAX : Self = Self ( i32:: MAX ) ;
198
+ /// Returns if `self` equals [`PollTimeout::NONE`].
199
+ pub fn is_none ( & self ) -> bool {
200
+ // > Specifying a negative value in timeout means an infinite timeout.
201
+ * self <= Self :: NONE
202
+ }
203
+ /// Returns if `self` does not equal [`PollTimeout::NONE`].
204
+ pub fn is_some ( & self ) -> bool {
205
+ !self . is_none ( )
206
+ }
207
+ /// Returns the timeout in milliseconds if there is some, otherwise returns `None`.
208
+ pub fn as_millis ( & self ) -> Option < i32 > {
209
+ self . is_some ( ) . then_some ( self . 0 )
210
+ }
211
+ /// Returns the timeout as a `Duration` if there is some, otherwise returns `None`.
212
+ pub fn timeout ( & self ) -> Option < Duration > {
213
+ self . as_millis ( ) . map ( |x|Duration :: from_millis ( u64:: try_from ( x) . unwrap ( ) ) )
214
+ }
215
+ }
216
+
217
+ /// Error type for integer conversions into `PollTimeout`.
218
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
219
+ pub enum PollTimeoutTryFromError {
220
+ /// Passing a value less than -1 is invalid on some systems, see
221
+ /// <https://man.freebsd.org/cgi/man.cgi?poll#end>.
222
+ TooNegative ,
223
+ /// Passing a value greater than `i32::MAX` is invalid.
224
+ TooPositive ,
225
+ }
226
+
227
+ impl std:: fmt:: Display for PollTimeoutTryFromError {
228
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
229
+ match self {
230
+ Self :: TooNegative => write ! ( f, "Passed a negative timeout less than -1." ) ,
231
+ Self :: TooPositive => write ! ( f, "Passed a positive timeout greater than `i32::MAX` milliseconds." )
232
+ }
233
+ }
234
+ }
235
+
236
+ impl std:: error:: Error for PollTimeoutTryFromError { }
237
+
238
+ impl < T : Into < PollTimeout > > From < Option < T > > for PollTimeout {
239
+ fn from ( x : Option < T > ) -> Self {
240
+ x. map_or ( Self :: NONE , |x| x. into ( ) )
241
+ }
242
+ }
243
+ impl TryFrom < Duration > for PollTimeout {
244
+ type Error = PollTimeoutTryFromError ;
245
+ fn try_from ( x : Duration ) -> std:: result:: Result < Self , Self :: Error > {
246
+ Ok ( Self ( i32:: try_from ( x. as_millis ( ) ) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) )
247
+ }
248
+ }
249
+ impl TryFrom < u128 > for PollTimeout {
250
+ type Error = PollTimeoutTryFromError ;
251
+ fn try_from ( x : u128 ) -> std:: result:: Result < Self , Self :: Error > {
252
+ Ok ( Self ( i32:: try_from ( x) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) )
253
+ }
254
+ }
255
+ impl TryFrom < u64 > for PollTimeout {
256
+ type Error = PollTimeoutTryFromError ;
257
+ fn try_from ( x : u64 ) -> std:: result:: Result < Self , Self :: Error > {
258
+ Ok ( Self ( i32:: try_from ( x) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) )
259
+ }
260
+ }
261
+ impl TryFrom < u32 > for PollTimeout {
262
+ type Error = PollTimeoutTryFromError ;
263
+ fn try_from ( x : u32 ) -> std:: result:: Result < Self , Self :: Error > {
264
+ Ok ( Self ( i32:: try_from ( x) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) )
265
+ }
266
+ }
267
+ impl From < u16 > for PollTimeout {
268
+ fn from ( x : u16 ) -> Self {
269
+ Self ( i32:: from ( x) )
270
+ }
271
+ }
272
+ impl From < u8 > for PollTimeout {
273
+ fn from ( x : u8 ) -> Self {
274
+ Self ( i32:: from ( x) )
275
+ }
276
+ }
277
+ impl TryFrom < i128 > for PollTimeout {
278
+ type Error = PollTimeoutTryFromError ;
279
+ fn try_from ( x : i128 ) -> std:: result:: Result < Self , Self :: Error > {
280
+ match x {
281
+ ..=-2 => Err ( PollTimeoutTryFromError :: TooNegative ) ,
282
+ -1 .. => Ok ( Self ( i32:: try_from ( x) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) ) ,
283
+ }
284
+ }
285
+ }
286
+ impl TryFrom < i64 > for PollTimeout {
287
+ type Error = PollTimeoutTryFromError ;
288
+ fn try_from ( x : i64 ) -> std:: result:: Result < Self , Self :: Error > {
289
+ match x {
290
+ ..=-2 => Err ( PollTimeoutTryFromError :: TooNegative ) ,
291
+ -1 .. => Ok ( Self ( i32:: try_from ( x) . map_err ( |_|PollTimeoutTryFromError :: TooPositive ) ?) ) ,
292
+ }
293
+ }
294
+ }
295
+ impl TryFrom < i32 > for PollTimeout {
296
+ type Error = PollTimeoutTryFromError ;
297
+ fn try_from ( x : i32 ) -> std:: result:: Result < Self , Self :: Error > {
298
+ match x {
299
+ ..=-2 => Err ( PollTimeoutTryFromError :: TooNegative ) ,
300
+ -1 .. => Ok ( Self ( x) ) ,
301
+ }
302
+ }
303
+ }
304
+ impl TryFrom < i16 > for PollTimeout {
305
+ type Error = PollTimeoutTryFromError ;
306
+ fn try_from ( x : i16 ) -> std:: result:: Result < Self , Self :: Error > {
307
+ match x {
308
+ ..=-2 => Err ( PollTimeoutTryFromError :: TooNegative ) ,
309
+ -1 .. => Ok ( Self ( i32:: from ( x) ) ) ,
310
+ }
311
+ }
312
+ }
313
+ impl TryFrom < i8 > for PollTimeout {
314
+ type Error = PollTimeoutTryFromError ;
315
+ fn try_from ( x : i8 ) -> std:: result:: Result < Self , Self :: Error > {
316
+ match x {
317
+ ..=-2 => Err ( PollTimeoutTryFromError :: TooNegative ) ,
318
+ -1 .. => Ok ( Self ( i32:: from ( x) ) ) ,
319
+ }
320
+ }
321
+ }
322
+ impl TryFrom < PollTimeout > for Duration {
323
+ type Error = ( ) ;
324
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , ( ) > {
325
+ x. timeout ( ) . ok_or ( ( ) )
326
+ }
327
+ }
328
+ impl TryFrom < PollTimeout > for u128 {
329
+ type Error = <Self as TryFrom < i32 > >:: Error ;
330
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
331
+ Self :: try_from ( x. 0 )
332
+ }
333
+ }
334
+ impl TryFrom < PollTimeout > for u64 {
335
+ type Error = <Self as TryFrom < i32 > >:: Error ;
336
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
337
+ Self :: try_from ( x. 0 )
338
+ }
339
+ }
340
+ impl TryFrom < PollTimeout > for u32 {
341
+ type Error = <Self as TryFrom < i32 > >:: Error ;
342
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
343
+ Self :: try_from ( x. 0 )
344
+ }
345
+ }
346
+ impl TryFrom < PollTimeout > for u16 {
347
+ type Error = <Self as TryFrom < i32 > >:: Error ;
348
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
349
+ Self :: try_from ( x. 0 )
350
+ }
351
+ }
352
+ impl TryFrom < PollTimeout > for u8 {
353
+ type Error = <Self as TryFrom < i32 > >:: Error ;
354
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
355
+ Self :: try_from ( x. 0 )
356
+ }
357
+ }
358
+ impl From < PollTimeout > for i128 {
359
+ fn from ( x : PollTimeout ) -> Self {
360
+ Self :: from ( x. 0 )
361
+ }
362
+ }
363
+ impl From < PollTimeout > for i64 {
364
+ fn from ( x : PollTimeout ) -> Self {
365
+ Self :: from ( x. 0 )
366
+ }
367
+ }
368
+ impl From < PollTimeout > for i32 {
369
+ fn from ( x : PollTimeout ) -> Self {
370
+ x. 0
371
+ }
372
+ }
373
+ impl TryFrom < PollTimeout > for i16 {
374
+ type Error = <Self as TryFrom < i32 > >:: Error ;
375
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
376
+ Self :: try_from ( x. 0 )
377
+ }
378
+ }
379
+ impl TryFrom < PollTimeout > for i8 {
380
+ type Error = <Self as TryFrom < i32 > >:: Error ;
381
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
382
+ Self :: try_from ( x. 0 )
383
+ }
384
+ }
385
+
182
386
/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
183
387
/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
184
388
///
@@ -195,13 +399,20 @@ libc_bitflags! {
195
399
///
196
400
/// Note that the timeout interval will be rounded up to the system clock
197
401
/// granularity, and kernel scheduling delays mean that the blocking
198
- /// interval may overrun by a small amount. Specifying a negative value
199
- /// in timeout means an infinite timeout. Specifying a timeout of zero
200
- /// causes `poll()` to return immediately, even if no file descriptors are
201
- /// ready.
202
- pub fn poll ( fds : & mut [ PollFd ] , timeout : libc:: c_int ) -> Result < libc:: c_int > {
402
+ /// interval may overrun by a small amount. Specifying a [`PollTimeout::NONE`]
403
+ /// in timeout means an infinite timeout. Specifying a timeout of
404
+ /// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file
405
+ /// descriptors are ready.
406
+ pub fn poll < T : Into < PollTimeout > > (
407
+ fds : & mut [ PollFd ] ,
408
+ timeout : T ,
409
+ ) -> Result < libc:: c_int > {
203
410
let res = unsafe {
204
- libc:: poll ( fds. as_mut_ptr ( ) . cast ( ) , fds. len ( ) as libc:: nfds_t , timeout)
411
+ libc:: poll (
412
+ fds. as_mut_ptr ( ) . cast ( ) ,
413
+ fds. len ( ) as libc:: nfds_t ,
414
+ i32:: from ( timeout. into ( ) ) ,
415
+ )
205
416
} ;
206
417
207
418
Errno :: result ( res)
0 commit comments