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
@@ -179,6 +179,184 @@ 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
+ impl < T : Into < PollTimeout > > From < Option < T > > for PollTimeout {
218
+ fn from ( x : Option < T > ) -> Self {
219
+ x. map_or ( Self :: NONE , |x| x. into ( ) )
220
+ }
221
+ }
222
+ impl TryFrom < Duration > for PollTimeout {
223
+ type Error = <i32 as TryFrom < u128 > >:: Error ;
224
+ fn try_from ( x : Duration ) -> std:: result:: Result < Self , Self :: Error > {
225
+ Ok ( Self ( i32:: try_from ( x. as_millis ( ) ) ?) )
226
+ }
227
+ }
228
+ impl TryFrom < u128 > for PollTimeout {
229
+ type Error = <i32 as TryFrom < u128 > >:: Error ;
230
+ fn try_from ( x : u128 ) -> std:: result:: Result < Self , Self :: Error > {
231
+ Ok ( Self ( i32:: try_from ( x) ?) )
232
+ }
233
+ }
234
+ impl TryFrom < u64 > for PollTimeout {
235
+ type Error = <i32 as TryFrom < u64 > >:: Error ;
236
+ fn try_from ( x : u64 ) -> std:: result:: Result < Self , Self :: Error > {
237
+ Ok ( Self ( i32:: try_from ( x) ?) )
238
+ }
239
+ }
240
+ impl TryFrom < u32 > for PollTimeout {
241
+ type Error = <i32 as TryFrom < u32 > >:: Error ;
242
+ fn try_from ( x : u32 ) -> std:: result:: Result < Self , Self :: Error > {
243
+ Ok ( Self ( i32:: try_from ( x) ?) )
244
+ }
245
+ }
246
+ impl From < u16 > for PollTimeout {
247
+ fn from ( x : u16 ) -> Self {
248
+ Self ( i32:: from ( x) )
249
+ }
250
+ }
251
+ impl From < u8 > for PollTimeout {
252
+ fn from ( x : u8 ) -> Self {
253
+ Self ( i32:: from ( x) )
254
+ }
255
+ }
256
+ impl TryFrom < i128 > for PollTimeout {
257
+ type Error = <i32 as TryFrom < i128 > >:: Error ;
258
+ fn try_from ( x : i128 ) -> std:: result:: Result < Self , Self :: Error > {
259
+ match x {
260
+ // > Specifying a negative value in timeout means an infinite timeout.
261
+ i128:: MIN ..=-1 => Ok ( Self :: NONE ) ,
262
+ millis @ 0 .. => Ok ( Self ( i32:: try_from ( millis) ?) ) ,
263
+ }
264
+ }
265
+ }
266
+ impl TryFrom < i64 > for PollTimeout {
267
+ type Error = <i32 as TryFrom < i64 > >:: Error ;
268
+ fn try_from ( x : i64 ) -> std:: result:: Result < Self , Self :: Error > {
269
+ match x {
270
+ i64:: MIN ..=-1 => Ok ( Self :: NONE ) ,
271
+ millis @ 0 .. => Ok ( Self ( i32:: try_from ( millis) ?) ) ,
272
+ }
273
+ }
274
+ }
275
+ impl From < i32 > for PollTimeout {
276
+ fn from ( x : i32 ) -> Self {
277
+ Self ( x)
278
+ }
279
+ }
280
+ impl From < i16 > for PollTimeout {
281
+ fn from ( x : i16 ) -> Self {
282
+ Self ( i32:: from ( x) )
283
+ }
284
+ }
285
+ impl From < i8 > for PollTimeout {
286
+ fn from ( x : i8 ) -> Self {
287
+ Self ( i32:: from ( x) )
288
+ }
289
+ }
290
+ impl TryFrom < PollTimeout > for Duration {
291
+ type Error = ( ) ;
292
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , ( ) > {
293
+ match x. timeout ( ) {
294
+ // SAFETY: When `x.timeout()` returns `Some(a)`, `a` is always non-negative.
295
+ Some ( millis) => Ok ( Duration :: from_millis ( unsafe {
296
+ u64:: try_from ( millis) . unwrap_unchecked ( )
297
+ } ) ) ,
298
+ None => Err ( ( ) ) ,
299
+ }
300
+ }
301
+ }
302
+ impl TryFrom < PollTimeout > for u128 {
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
+ impl TryFrom < PollTimeout > for u64 {
309
+ type Error = <Self as TryFrom < i32 > >:: Error ;
310
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
311
+ Self :: try_from ( x. 0 )
312
+ }
313
+ }
314
+ impl TryFrom < PollTimeout > for u32 {
315
+ type Error = <Self as TryFrom < i32 > >:: Error ;
316
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
317
+ Self :: try_from ( x. 0 )
318
+ }
319
+ }
320
+ impl TryFrom < PollTimeout > for u16 {
321
+ type Error = <Self as TryFrom < i32 > >:: Error ;
322
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
323
+ Self :: try_from ( x. 0 )
324
+ }
325
+ }
326
+ impl TryFrom < PollTimeout > for u8 {
327
+ type Error = <Self as TryFrom < i32 > >:: Error ;
328
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
329
+ Self :: try_from ( x. 0 )
330
+ }
331
+ }
332
+ impl From < PollTimeout > for i128 {
333
+ fn from ( x : PollTimeout ) -> Self {
334
+ Self :: from ( x. 0 )
335
+ }
336
+ }
337
+ impl From < PollTimeout > for i64 {
338
+ fn from ( x : PollTimeout ) -> Self {
339
+ Self :: from ( x. 0 )
340
+ }
341
+ }
342
+ impl From < PollTimeout > for i32 {
343
+ fn from ( x : PollTimeout ) -> Self {
344
+ x. 0
345
+ }
346
+ }
347
+ impl TryFrom < PollTimeout > for i16 {
348
+ type Error = <Self as TryFrom < i32 > >:: Error ;
349
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
350
+ Self :: try_from ( x. 0 )
351
+ }
352
+ }
353
+ impl TryFrom < PollTimeout > for i8 {
354
+ type Error = <Self as TryFrom < i32 > >:: Error ;
355
+ fn try_from ( x : PollTimeout ) -> std:: result:: Result < Self , Self :: Error > {
356
+ Self :: try_from ( x. 0 )
357
+ }
358
+ }
359
+
182
360
/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
183
361
/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
184
362
///
@@ -195,13 +373,20 @@ libc_bitflags! {
195
373
///
196
374
/// Note that the timeout interval will be rounded up to the system clock
197
375
/// 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 > {
376
+ /// interval may overrun by a small amount. Specifying a [`PollTimeout::NONE`]
377
+ /// in timeout means an infinite timeout. Specifying a timeout of
378
+ /// [`PollTimeout::ZERO`] causes `poll()` to return immediately, even if no file
379
+ /// descriptors are ready.
380
+ pub fn poll < T : Into < PollTimeout > > (
381
+ fds : & mut [ PollFd ] ,
382
+ timeout : T ,
383
+ ) -> Result < libc:: c_int > {
203
384
let res = unsafe {
204
- libc:: poll ( fds. as_mut_ptr ( ) . cast ( ) , fds. len ( ) as libc:: nfds_t , timeout)
385
+ libc:: poll (
386
+ fds. as_mut_ptr ( ) . cast ( ) ,
387
+ fds. len ( ) as libc:: nfds_t ,
388
+ i32:: from ( timeout. into ( ) ) ,
389
+ )
205
390
} ;
206
391
207
392
Errno :: result ( res)
0 commit comments