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