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