11//! Wait for events to trigger on specific file descriptors
22use std:: os:: unix:: io:: { AsFd , AsRawFd , BorrowedFd } ;
3+ use std:: time:: Duration ;
34
45use crate :: errno:: Errno ;
56use crate :: Result ;
6-
77/// This is a wrapper around `libc::pollfd`.
88///
99/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
@@ -168,6 +168,180 @@ libc_bitflags! {
168168 }
169169}
170170
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+
171345/// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
172346/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
173347///
@@ -184,16 +358,19 @@ libc_bitflags! {
184358///
185359/// Note that the timeout interval will be rounded up to the system clock
186360/// 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 > {
192369 let res = unsafe {
193370 libc:: poll (
194371 fds. as_mut_ptr ( ) as * mut libc:: pollfd ,
195372 fds. len ( ) as libc:: nfds_t ,
196- timeout,
373+ i32 :: from ( timeout. into ( ) ) ,
197374 )
198375 } ;
199376
0 commit comments