timer_deque_rs/timer_portable/unix/
mod.rs

1
2
3#[cfg(
4     any(
5            target_os = "freebsd",
6            target_os = "dragonfly",
7            target_os = "netbsd",
8            target_os = "openbsd",
9            target_os = "macos",
10        )
11    )
12]
13pub mod bsd;
14
15#[cfg(target_os = "linux")]
16pub mod linux;
17
18use std::{fmt, io};
19pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
20
21pub use nix::libc::{self, ECANCELED, EWOULDBLOCK};
22
23// --- event watch ---
24#[cfg(target_os = "linux")]
25pub use linux::timer_poll::TimerEventWatch;
26
27
28#[cfg(
29    any(
30        target_os = "freebsd",
31        target_os = "dragonfly",
32        target_os = "netbsd",
33        target_os = "openbsd",
34        target_os = "macos",
35    )
36)]
37pub use bsd::TimerEventWatch;
38
39
40// --- timer id ---
41#[cfg(target_os = "linux")]
42pub use linux::timer_fd_linux::TimerFdInternal;
43
44use crate::{AbsoluteTime, RelativeTime, TimerFd, TimerReadRes, timer_portable::{TimerExpMode, TimerId, timer::ModeTimeType}};
45
46#[cfg(
47    all(
48        any(
49            target_os = "freebsd",
50            target_os = "dragonfly",
51            target_os = "netbsd",
52            target_os = "openbsd",
53            target_os = "macos",
54        ),
55        feature = "bsd_use_timerfd"
56    )
57)]
58pub use bsd::timer_fd_bsd::TimerFdInternal;
59
60#[cfg(
61    all(
62        any(
63            target_os = "freebsd",
64            target_os = "dragonfly",
65            target_os = "netbsd",
66            target_os = "openbsd",
67            target_os = "macos",
68        ),
69        not(feature = "bsd_use_timerfd")
70    )
71)]
72pub use bsd::timer_kqueue_fd_bsd::TimerFdInternal;
73
74
75use bitflags::bitflags;
76
77/// A timer type
78#[allow(non_camel_case_types)]
79#[repr(i32)]
80#[derive(Debug)]
81pub enum TimerType
82{
83    /// A settable system-wide real-time clock.
84    CLOCK_REALTIME = libc::CLOCK_REALTIME,
85
86    /// A nonsettable monotonically increasing clock that measures  time
87    /// from some unspecified point in the past that does not change af‐
88    /// ter system startup.
89
90    CLOCK_MONOTONIC = libc::CLOCK_MONOTONIC,
91
92    
93    /// Like CLOCK_MONOTONIC, this is a monotonically increasing  clock.
94    /// However,  whereas the CLOCK_MONOTONIC clock does not measure the
95    /// time while a system is suspended, the CLOCK_BOOTTIME clock  does
96    /// include  the time during which the system is suspended.  This is
97    /// useful  for  applications  that  need   to   be   suspend-aware.
98    /// CLOCK_REALTIME is not suitable for such applications, since that
99    /// clock is affected by discontinuous changes to the system clock.
100    #[cfg(target_os = "linux")]
101    CLOCK_BOOTTIME = libc::CLOCK_BOOTTIME,
102
103    /// This clock is like CLOCK_REALTIME, but will wake the  system  if
104    /// it  is suspended.  The caller must have the CAP_WAKE_ALARM capa‐
105    /// bility in order to set a timer against this clock.
106    #[cfg(target_os = "linux")]
107    CLOCK_REALTIME_ALARM = libc::CLOCK_REALTIME_ALARM,
108
109    /// This clock is like CLOCK_BOOTTIME, but will wake the  system  if
110    /// it  is suspended.  The caller must have the CAP_WAKE_ALARM capa‐
111    /// bility in order to set a timer against this clock.
112    #[cfg(target_os = "linux")]
113    CLOCK_BOOTTIME_ALARM = libc::CLOCK_BOOTTIME_ALARM,
114}
115
116impl From<TimerType> for libc::clockid_t 
117{
118    fn from(value: TimerType) -> Self 
119    {
120        return value as libc::clockid_t;
121    }
122}
123
124
125bitflags! {     
126    /// Flags controling the type of the timer type.  
127    #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] 
128    pub struct TimerFlags: i32  
129    {     
130        /// Set the O_NONBLOCK file status flag on the open file  de‐
131        /// scription  (see  open(2)) referred to by the new file de‐
132        /// scriptor.  Using this flag saves extra calls to  fcntl(2)
133        /// to achieve the same result.
134        const TFD_NONBLOCK = libc::TFD_NONBLOCK;
135
136        /// Set  the  close-on-exec (FD_CLOEXEC) flag on the new file
137        /// descriptor.  See the description of the O_CLOEXEC flag in
138        /// open(2) for reasons why this may be useful.
139        const TFD_CLOEXEC = libc::TFD_CLOEXEC;
140    }
141}
142
143
144bitflags! {     
145    /// A bit mask that can include the values.
146    #[derive(Default, Debug, Eq, PartialEq, Clone, Copy)] 
147    pub struct TimerSetTimeFlags: i32  
148    {     
149        /// > Interpret  new_value.it_value as an absolute value on the timer's
150        /// > clock.  The timer will expire when the value of the timer's clock
151        /// > reaches the value specified in new_value.it_value.
152        const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
153
154        /// > If this flag is specified along with  TFD_TIMER_ABSTIME  and  the
155        /// > clock  for  this timer is CLOCK_REALTIME or CLOCK_REALTIME_ALARM,
156        /// > then mark this timer as cancelable if the real-time clock  under‐
157        /// > goes  a  discontinuous change (settimeofday(2), clock_settime(2),
158        /// > or similar).  When  such  changes  occur,  a  current  or  future
159        /// > read(2)  from  the file descriptor will fail with the error 
160        /// > ECANCELED.
161        const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET;
162    }
163}
164
165// ------- TIMER ID -----
166impl From<RawFd> for TimerId
167{
168    fn from(value: RawFd) -> Self 
169    {
170        return Self(value as usize);
171    }
172}
173
174impl From<u64> for TimerId
175{
176    fn from(value: u64) -> Self 
177    {
178        return Self(value as usize);
179    }
180}
181
182/*
183impl From<&TimerFd> for TimerId
184{
185    fn from(value: &TimerFd) -> Self 
186    {
187        return Self(value.as_raw_handle() as usize);
188    }
189}*/
190
191
192impl PartialEq<RawFd> for TimerId
193{
194    fn eq(&self, other: &RawFd) -> bool 
195    {
196        return self.0 == *other as usize;
197    }
198}
199
200// ----- / TIMER ID / ---
201
202pub trait UnixFd: AsFd + AsRawFd + PartialEq<RawFd> {}
203
204// ---- TimerFd ------
205
206/// Implementation for the TimrFD.
207impl UnixFd for TimerFd {}
208
209impl PartialEq<RawFd> for TimerFd
210{
211    fn eq(&self, other: &RawFd) -> bool 
212    {
213        return self.as_raw_fd() == *other;
214    }
215}
216
217impl AsFd for TimerFd
218{
219    fn as_fd(&self) -> BorrowedFd<'_> 
220    {
221        return self.get_timer().as_fd();
222    }
223}
224
225impl AsRawFd for TimerFd
226{
227    fn as_raw_fd(&self) -> RawFd 
228    {
229        return self.get_timer().as_raw_fd();
230    }
231}
232
233// -----------------------
234
235pub use nix::libc::{itimerspec, timespec};
236
237/// Converts from [itimerspec] into [TimerExpMode] of the `TIMERTYPE`.
238impl<TIMERTYPE: ModeTimeType> From<itimerspec> for TimerExpMode<TIMERTYPE>
239{
240    fn from(value: itimerspec) -> Self 
241    {
242        if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0 &&
243            value.it_value.tv_sec == 0 && value.it_value.tv_nsec == 0
244        {
245            // unset
246            return Self::None;
247        }
248        else if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0
249        {
250            // one shot
251            return 
252                Self::OneShot
253                { 
254                    timeout: TIMERTYPE::from(value.it_value) 
255                };
256        }
257        else if value.it_interval.tv_sec == value.it_value.tv_sec &&
258            value.it_interval.tv_nsec == value.it_value.tv_nsec
259        {
260            // interval
261            return 
262                Self::Interval
263                { 
264                    interv_tm: TIMERTYPE::from(value.it_interval) 
265                };
266        }
267        else
268        {
269            // delayed interval
270            return 
271                Self::IntervalDelayed 
272                { 
273                    delay_tm: TIMERTYPE::from(value.it_value),
274                    interv_tm: TIMERTYPE::from(value.it_interval) 
275                };
276        }
277    }
278}
279
280impl From<timespec> for RelativeTime
281{
282    fn from(time_spec: timespec) -> Self 
283    {
284        return   
285            Self::new_time(time_spec.tv_sec, time_spec.tv_nsec);
286    }
287}
288
289
290impl From<timespec> for AbsoluteTime
291{
292    fn from(time_spec: timespec) -> Self 
293    {
294        return 
295            unsafe 
296            { 
297                Self::new_time_unchecked(time_spec.tv_sec, time_spec.tv_nsec) 
298            };
299    }
300}
301
302impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> From<io::Error> for TimerReadRes<T>
303{
304    fn from(value: io::Error) -> Self 
305    {
306        if let Some(errn) = value.raw_os_error()
307        {
308            if errn == ECANCELED
309            {
310                return Self::Cancelled;
311            }
312            else if errn == EWOULDBLOCK
313            {
314                return Self::WouldBlock;
315            }
316        }
317
318        return Self::Cancelled;
319    }
320}
321
322impl<TIMERTYPE: ModeTimeType> From<TimerExpMode<TIMERTYPE>> for itimerspec
323{
324    fn from(value: TimerExpMode<TIMERTYPE>) -> Self 
325    {
326        return (&value).into();
327    }
328}
329
330/// Converts from the reference to [TimerExpMode] of the `TIMERTYPE` into the 
331/// [itimerspec].
332impl<TIMERTYPE: ModeTimeType> From<&TimerExpMode<TIMERTYPE>> for itimerspec
333{
334    fn from(value: &TimerExpMode<TIMERTYPE>) -> Self 
335    {
336        match value
337        {
338            TimerExpMode::None => 
339                return 
340                    itimerspec 
341                    {
342                        it_interval: timespec 
343                        {
344                            tv_sec: 0,
345                            tv_nsec: 0,
346                        },
347                        it_value: timespec
348                        {
349                            tv_sec: 0,
350                            tv_nsec: 0,
351                        },
352                    },
353            TimerExpMode::OneShot{ timeout} =>
354                return 
355                    itimerspec 
356                    {
357                        it_interval: timespec 
358                        {
359                            tv_sec: 0,
360                            tv_nsec: 0,
361                        },
362                        it_value: timespec
363                        {
364                            tv_sec: timeout.get_sec(),
365                            tv_nsec: timeout.get_nsec(),
366                        },
367                    },
368            TimerExpMode::IntervalDelayed{ delay_tm, interv_tm } => 
369                return 
370                    itimerspec 
371                    {
372                        it_interval: timespec 
373                        {
374                            tv_sec: interv_tm.get_sec(),
375                            tv_nsec: interv_tm.get_nsec(),
376                        },
377                        it_value: timespec
378                        {
379                            tv_sec: delay_tm.get_sec(),
380                            tv_nsec: delay_tm.get_nsec(),
381                        },
382                    },
383            TimerExpMode::Interval{ interv_tm } => 
384                return 
385                    itimerspec 
386                    {
387                        it_interval: timespec 
388                        {
389                            tv_sec: interv_tm.get_sec(),
390                            tv_nsec: interv_tm.get_nsec(),
391                        },
392                        it_value: timespec
393                        {
394                            tv_sec: interv_tm.get_sec(),
395                            tv_nsec: interv_tm.get_nsec(),
396                        },
397                    }
398        }
399    }
400}
401
402
403
404
405
406#[cfg(all(target_family = "unix", feature = "enable_mio_compat"))]
407pub mod mio_compat
408{
409    use std::{io, os::fd::{AsRawFd, RawFd}};
410
411    use mio::{Token, unix::SourceFd};
412
413    use crate::timer_portable::timer::TimerFdMioCompat;
414
415    use super::TimerFd;
416
417    impl mio::event::Source for TimerFd 
418    {
419        fn register(
420            &mut self,
421            registry: &mio::Registry,
422            token: mio::Token,
423            interests: mio::Interest,
424        ) -> io::Result<()> 
425        {
426            return 
427                SourceFd(&self.as_raw_fd()).register(registry, token, interests);
428        }
429
430        fn reregister(
431            &mut self,
432            registry: &mio::Registry,
433            token: mio::Token,
434            interests: mio::Interest,
435        ) -> io::Result<()> 
436        {
437            return 
438                SourceFd(&self.as_raw_fd()).reregister(registry, token, interests);
439        }
440
441        fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()> 
442        {
443            return 
444                SourceFd(&self.as_raw_fd()).deregister(registry)
445        }
446    }
447
448    
449    impl PartialEq<Token> for TimerFd
450    {
451        fn eq(&self, other: &Token) -> bool 
452        {
453            return self.as_raw_fd() == other.0 as RawFd;
454        }
455    }
456
457    impl TimerFdMioCompat for TimerFd
458    { 
459        fn get_token(&self) -> Token
460        {
461            return Token(self.as_raw_fd() as usize);
462        }
463    }
464}