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