timer_deque_rs/timer_portable/
timer.rs

1/*-
2 * timer-rs - a Rust crate which provides timer and timer queues based on target OS
3 *  functionality.
4 * 
5 * Copyright (C) 2025 Aleksandr Morozov
6 * 
7 * The timer-rs crate can be redistributed and/or modified
8 * under the terms of either of the following licenses:
9 *
10 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
11 *                     
12 *   2. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
13 */
14
15use std::{borrow::Cow, cmp::Ordering, fmt, io::{self}, ops, time::Duration};
16
17use chrono::{DateTime, TimeZone};
18use nix::libc::{self, ECANCELED, EWOULDBLOCK};
19use bitflags::bitflags;
20
21use crate::{common, timer_portable::portable_error::TimerPortResult};
22
23#[cfg(target_os = "linux")]
24pub use super::linux::timer_fd_linux::*;
25
26#[cfg(any(
27    target_os = "freebsd",
28    target_os = "dragonfly",
29    target_os = "netbsd",
30    target_os = "openbsd",
31    target_os = "macos",
32))]
33pub use super::bsd::timer_kqueue_bsd::*;
34
35
36/// A timer type
37#[allow(non_camel_case_types)]
38#[derive(Debug)]
39pub enum TimerType
40{
41    /// A settable system-wide real-time clock.
42    CLOCK_REALTIME,
43
44    /// A nonsettable monotonically increasing clock that measures  time
45    /// from some unspecified point in the past that does not change af‐
46    /// ter system startup.
47
48    CLOCK_MONOTONIC,
49
50    /// Like CLOCK_MONOTONIC, this is a monotonically increasing  clock.
51    /// However,  whereas the CLOCK_MONOTONIC clock does not measure the
52    /// time while a system is suspended, the CLOCK_BOOTTIME clock  does
53    /// include  the time during which the system is suspended.  This is
54    /// useful  for  applications  that  need   to   be   suspend-aware.
55    /// CLOCK_REALTIME is not suitable for such applications, since that
56    /// clock is affected by discontinuous changes to the system clock.
57    CLOCK_BOOTTIME,
58
59    /// This clock is like CLOCK_REALTIME, but will wake the  system  if
60    /// it  is suspended.  The caller must have the CAP_WAKE_ALARM capa‐
61    /// bility in order to set a timer against this clock.
62    CLOCK_REALTIME_ALARM,
63
64    /// This clock is like CLOCK_BOOTTIME, but will wake the  system  if
65    /// it  is suspended.  The caller must have the CAP_WAKE_ALARM capa‐
66    /// bility in order to set a timer against this clock.
67    CLOCK_BOOTTIME_ALARM,
68}
69
70impl Into<libc::clockid_t> for TimerType 
71{
72    fn into(self) -> libc::clockid_t
73    {
74        match self
75        {
76            Self::CLOCK_REALTIME        => return libc::CLOCK_REALTIME,
77            Self::CLOCK_MONOTONIC       => return libc::CLOCK_MONOTONIC,
78            #[cfg(target_os = "linux")]
79            Self::CLOCK_BOOTTIME        => return libc::CLOCK_BOOTTIME,
80            #[cfg(target_os = "linux")]
81            Self::CLOCK_REALTIME_ALARM  => return libc::CLOCK_REALTIME_ALARM,
82            #[cfg(target_os = "linux")]
83            Self::CLOCK_BOOTTIME_ALARM  => return libc::CLOCK_BOOTTIME_ALARM,
84            #[cfg(any(
85                target_os = "freebsd",
86                target_os = "dragonfly",
87                target_os = "netbsd",
88                target_os = "openbsd",
89                target_os = "macos",
90            ))]
91            _ => return libc::CLOCK_REALTIME,
92        }
93    }
94}
95
96#[cfg(target_os = "linux")]
97bitflags! {     
98    /// Flags controling the type of the timer type.  
99    #[derive(Default)] 
100    pub struct TimerFlags: i32  
101    {     
102        /// Set the O_NONBLOCK file status flag on the open file  de‐
103        /// scription  (see  open(2)) referred to by the new file de‐
104        /// scriptor.  Using this flag saves extra calls to  fcntl(2)
105        /// to achieve the same result.
106        const TFD_NONBLOCK = libc::TFD_NONBLOCK;
107
108        /// Set  the  close-on-exec (FD_CLOEXEC) flag on the new file
109        /// descriptor.  See the description of the O_CLOEXEC flag in
110        /// open(2) for reasons why this may be useful.
111        const TFD_CLOEXEC = libc::TFD_CLOEXEC;
112    }
113}
114
115#[cfg(any(
116    target_os = "freebsd",
117    target_os = "dragonfly",
118    target_os = "netbsd",
119    target_os = "openbsd",
120    target_os = "macos",
121))]
122bitflags! {     
123    /// Flags controling the type of the timer type.   
124    #[derive(Default)] 
125    pub struct TimerFlags: i32  
126    {     
127        /// Not appliciable
128        const TFD_NONBLOCK = 0;
129
130        /// Not appliciable.
131        const TFD_CLOEXEC = 0;
132    }
133}
134
135#[cfg(target_os = "linux")]
136bitflags! {     
137    /// A bit mask that can include the values.
138    #[derive(Default, Debug, Eq, PartialEq, Clone, Copy)] 
139    pub struct TimerSetTimeFlags: i32  
140    {     
141        /// > Interpret  new_value.it_value as an absolute value on the timer's
142        /// > clock.  The timer will expire when the value of the timer's clock
143        /// > reaches the value specified in new_value.it_value.
144        const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
145
146        /// > If this flag is specified along with  TFD_TIMER_ABSTIME  and  the
147        /// > clock  for  this timer is CLOCK_REALTIME or CLOCK_REALTIME_ALARM,
148        /// > then mark this timer as cancelable if the real-time clock  under‐
149        /// > goes  a  discontinuous change (settimeofday(2), clock_settime(2),
150        /// > or similar).  When  such  changes  occur,  a  current  or  future
151        /// > read(2)  from  the file descriptor will fail with the error 
152        /// > ECANCELED.
153        const TFD_TIMER_CANCEL_ON_SET = (1 << 1);
154    }
155}
156
157#[cfg(any(
158    target_os = "freebsd",
159    target_os = "dragonfly",
160    target_os = "netbsd",
161    target_os = "openbsd",
162    target_os = "macos",
163))]
164
165bitflags! {     
166    /// A bit mask that can include the values. 
167    #[derive(Default)] 
168    pub struct TimerSetTimeFlags: i32  
169    {     
170        /// Not appliciable.
171        const TFD_TIMER_ABSTIME = 0;
172
173        /// Not appliciable.
174        const TFD_TIMER_CANCEL_ON_SET = 0;
175    }
176}
177
178/// A trait which defines a standart interface for the different time types i.e
179/// 
180/// - [RelativeTime] a relative time to the system's clock.
181/// 
182/// - [AbsoluteTime] an absolute time to the systmem's clock.
183/// 
184/// This is an internal trait and should not be exposed to the outside of the crate.
185pub trait ModeTimeType: Eq + PartialEq + Ord + PartialOrd + fmt::Display + fmt::Debug + Clone + Copy
186{
187    /// Creates new instance from the two components: seconds and subnanoseconds of the seconds.
188    /// 
189    /// # Arguments
190    /// 
191    /// `tv_sec` - [i64] - a seconds.
192    /// 
193    /// `tv_nsec` - [i64] - a nanosecond fraction which should not exceed 999_999_999ns otherwise
194    /// the secodns will be adjusted.
195    /// 
196    /// # Returns
197    /// 
198    /// An instance is returend.
199    fn new(tv_sec: i64, tv_nsec: i64) -> Self where Self: Sized;
200
201    /// Returns the seconds without the nanoseconds fraction.
202    fn get_sec(&self) -> i64;
203
204    /// Returns the nanoseconds fraction from seconds, not a full time in nanoseconds.
205    fn get_nsec(&self) -> i64;
206
207    /// Verifies that the timer is not set to zero. For the [RelativeTime] it always returns true.
208    fn is_value_valid(&self) -> bool;
209
210    /// Returns the [TimerSetTimeFlags] which are autoinitialized for both types. This flags
211    /// should be passed to timer.
212    fn get_flags() -> TimerSetTimeFlags;
213}
214
215/// A `relative` time i.e time which is not binded to the system's clock.
216#[derive(Debug, PartialEq, Eq, Clone, Copy)]
217pub struct RelativeTime
218{
219    /// Seconds
220    time_sec: i64,
221
222    /// A fraction of ns from second
223    time_nsec: i64,
224}
225
226/// Converts the [Duration] to [RelativeTime] taking the `subsec_nanos`
227/// for the `time_nsec`.
228impl From<Duration> for RelativeTime
229{
230    fn from(value: Duration) -> Self 
231    {
232        return Self
233        {
234            time_sec: 
235                value.as_secs() as i64,
236            time_nsec: 
237                value.subsec_nanos() as i64,
238        };
239    }
240}
241
242impl Ord for RelativeTime
243{
244    fn cmp(&self, other: &Self) -> Ordering 
245    {
246        return 
247            self
248                .time_sec
249                .cmp(&other.time_sec)
250                .then(
251                    self
252                        .time_nsec
253                        .cmp(&other.time_nsec)
254                );
255    }
256}
257
258impl PartialOrd for RelativeTime
259{
260    fn partial_cmp(&self, other: &Self) -> Option<Ordering> 
261    {
262        return Some(self.cmp(other));
263    }
264}
265
266impl fmt::Display for RelativeTime
267{
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
269    {
270        write!(f, "[relative] sec: {}, nsec: {}", self.time_sec, self.time_nsec)
271    }
272}
273
274impl ModeTimeType for RelativeTime
275{
276    fn new(tv_sec: i64, tv_nsec: i64) -> RelativeTime
277    {
278        return   
279            Self::new_time(tv_sec, tv_nsec);
280    }
281    
282    fn get_sec(&self) -> i64 
283    {
284        return self.time_sec;
285    }
286    
287    fn get_nsec(&self) -> i64 {
288
289        return self.time_nsec;
290    }
291
292    fn is_value_valid(&self) -> bool 
293    {
294        return true;    
295    }
296
297    fn get_flags() -> TimerSetTimeFlags
298    {
299        return TimerSetTimeFlags::empty();
300    }
301}
302
303impl RelativeTime
304{
305    /// max nanoseconds
306    pub const MAX_NS: i64 = 1_000_000_000;
307
308    /// Creates new instance for relative time accepting the user input.
309    /// 
310    /// Automatically corrects the `time_nsec` value if it is larger than
311    /// 999_999_999ns.
312    /// 
313    /// # Arguments
314    /// 
315    /// `time_sec` - [i64] a seconds in relative notation.
316    /// 
317    /// `time_nsec` - [i64] nanoseconds of relative seconds value. Should not be 
318    ///     larger than 999_999_999 which is defined by const [Self::MAX_NS]. In
319    ///     case if it is larger, the `nsec` will be rounded and an extra secons
320    ///     will be added.
321    pub 
322    fn new_time(time_sec: i64, time_nsec: i64) -> Self
323    {
324        let extra_sec = time_nsec / Self::MAX_NS;
325        let nsec_new = time_nsec % Self::MAX_NS;
326
327        return 
328            Self
329            { 
330                time_nsec: nsec_new, 
331                time_sec: time_sec + extra_sec,
332            };
333    }
334}
335
336/// An `absolute` time which are binded to the system's clock
337/// and never be zero except when timer is reset.
338#[derive(Debug, PartialEq, Eq, Clone, Copy)]
339pub struct AbsoluteTime
340{
341    /// A full seconds.
342    time_sec: i64,
343
344    /// A fraction (subset) of nanoseconds from the second.
345    time_nsec: i64,
346}
347
348/// Convers the `chrono` [DateTime<Local>] into the [AbsoluteTime]
349/// taking the `ns` fraction of a second (subsec_nano) using
350/// `timestamp_subsec_nanos` function.
351/*impl From<DateTime<Local>> for AbsoluteTime
352{
353    fn from(value: DateTime<Local>) -> Self 
354    {
355        return Self
356        {
357            time_sec: 
358                value.timestamp(), 
359            time_nsec: 
360                value.timestamp_subsec_nanos() as i64,
361        };
362    }
363}*/
364
365/// Convers the `chrono` [DateTime<TZ>] into the [AbsoluteTime] using 
366/// the `TZ` [TimeZone]  taking the `ns` fraction of a second (subsec_nano) 
367/// using `timestamp_subsec_nanos` function.
368impl<TZ: TimeZone> From<DateTime<TZ>> for AbsoluteTime
369{
370    fn from(value: DateTime<TZ>) -> Self 
371    {
372        return Self
373        {
374            time_sec: 
375                value.timestamp(), 
376            time_nsec: 
377                value.timestamp_subsec_nanos() as i64,
378        };
379    }
380}
381
382/// Converts the [Duration] to [RelativeTime] taking the `subsec_nanos`
383/// for the `time_nsec`.
384impl From<Duration> for AbsoluteTime
385{
386    fn from(value: Duration) -> Self 
387    {
388        return Self
389        {
390            time_sec: 
391                value.as_secs() as i64,
392            time_nsec: 
393                value.subsec_nanos() as i64,
394        };
395    }
396}
397
398impl Ord for AbsoluteTime
399{
400    fn cmp(&self, other: &Self) -> Ordering 
401    {
402        return 
403            self
404                .time_sec
405                .cmp(&other.time_sec)
406                .then(
407                    self
408                        .time_nsec
409                        .cmp(&other.time_nsec)
410                );
411    }
412}
413
414impl PartialOrd for AbsoluteTime
415{
416    fn partial_cmp(&self, other: &Self) -> Option<Ordering> 
417    {
418        return Some(self.cmp(other));
419    }
420}
421
422impl ops::AddAssign<RelativeTime> for AbsoluteTime
423{
424    fn add_assign(&mut self, rhs: RelativeTime) 
425    {
426        self.time_nsec += rhs.time_nsec;
427        let add_sec = self.time_nsec / Self::MAX_NS;
428
429        if add_sec > 0
430        {
431            self.time_nsec %=  Self::MAX_NS;
432        }
433        
434        self.time_sec += rhs.time_sec + add_sec;
435    }
436}
437
438impl ops::Add<RelativeTime> for AbsoluteTime
439{
440    type Output = AbsoluteTime;
441
442    fn add(mut self, rhs: RelativeTime) -> Self::Output 
443    {
444        self += rhs;
445
446        return self;
447    }
448}
449
450impl ops::SubAssign<RelativeTime> for AbsoluteTime
451{
452    fn sub_assign(&mut self, mut rhs: RelativeTime) 
453    {
454
455        let mut nsec = self.time_nsec - rhs.time_nsec;
456
457        if nsec < 0
458        {
459            rhs.time_sec += 1;
460
461            nsec = Self::MAX_NS + nsec;
462        }
463        
464        self.time_nsec = nsec;
465        self.time_sec -= rhs.time_sec;
466
467        return;
468    }
469}
470
471impl ops::Sub<RelativeTime> for AbsoluteTime
472{
473    type Output = AbsoluteTime;
474
475    fn sub(mut self, rhs: RelativeTime) -> Self::Output 
476    {
477        self -= rhs;
478
479        return self;
480    }
481}
482
483impl ops::SubAssign for AbsoluteTime
484{
485    fn sub_assign(&mut self, mut rhs: Self) 
486    {
487
488        let mut nsec = self.time_nsec - rhs.time_nsec;
489
490        if nsec < 0
491        {
492            rhs.time_sec += 1;
493
494            nsec = Self::MAX_NS + nsec;
495        }
496        
497        self.time_nsec = nsec;
498        self.time_sec -= rhs.time_sec;
499
500        return;
501    }
502}
503
504impl ops::Sub for AbsoluteTime
505{
506    type Output = AbsoluteTime;
507
508    fn sub(mut self, rhs: Self) -> Self::Output 
509    {
510        self -= rhs;
511
512        return self;
513    }
514}
515
516
517impl fmt::Display for AbsoluteTime
518{
519    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
520    {
521        write!(f, "[absolute] {}.{}sec", self.time_sec, self.time_nsec)
522    }
523}
524
525
526impl ModeTimeType for AbsoluteTime
527{
528    fn new(tv_sec: i64, tv_nsec: i64) -> Self where Self: Sized 
529    {
530        return 
531            Self::new_time(tv_sec, tv_nsec);
532    }
533
534    fn get_sec(&self) -> i64 
535    {
536        return self.time_sec;
537    }
538    
539    fn get_nsec(&self) -> i64 
540    {
541
542        return self.time_nsec;
543    }
544
545    fn is_value_valid(&self) -> bool 
546    {
547        return self.time_nsec != 0 || self.time_sec != 0;
548    }
549
550    fn get_flags() -> TimerSetTimeFlags
551    {
552        return TimerSetTimeFlags::TFD_TIMER_ABSTIME | TimerSetTimeFlags::TFD_TIMER_CANCEL_ON_SET;
553    }
554}
555
556impl AbsoluteTime
557{
558    /// max nanoseconds
559    pub const MAX_NS: i64 = 1_000_000_000;//999_999_999;
560}
561
562impl AbsoluteTime
563{
564    /// Creates an instance with the current local time.
565    pub 
566    fn now() -> Self
567    {
568        let value = common::get_current_timestamp();
569
570        return Self
571        {
572            time_sec: value.timestamp(), 
573            time_nsec: value.timestamp_subsec_nanos() as i64,
574        }
575    }
576
577    /// Creates new instance for absolute time accepting the user input.
578    /// 
579    /// Automatically corrects the `time_nsec` value if it is larger than
580    /// 999_999_999ns.
581    /// 
582    /// # Arguments
583    /// 
584    /// `time_sec` - [i64] a seconds in absolute notation.
585    /// 
586    /// `time_nsec` - [i64] nanoseconds of absolute seconds value. Should not be 
587    ///     larger than 999_999_999 which is defined by const [Self::MAX_NS]. In
588    ///     case if it is larger, the `nsec` will be rounded and an extra secons
589    ///     will be added.
590    /// 
591    /// # Returns 
592    /// 
593    /// An instance is returned. May panic on overflow.
594    pub 
595    fn new_time(time_sec: i64, time_nsec: i64) -> Self
596    {
597        let extra_sec = time_nsec / Self::MAX_NS;
598        let nsec_new = time_nsec % Self::MAX_NS;
599
600        return 
601            Self
602            { 
603                time_nsec: nsec_new, 
604                time_sec: time_sec + extra_sec,
605            };
606    }
607
608    /// Compares only full seconds without nanoseconds fraction (subnano).
609    pub 
610    fn seconds_cmp(&self, other: &Self) -> Ordering
611    {
612        return self.time_sec.cmp(&other.time_sec);
613    }
614
615    pub 
616    fn add_sec(mut self, seconds: i64) -> Self
617    {
618        self.time_sec += seconds;
619
620        return self;
621    }
622
623    pub 
624    fn reset_nsec(mut self) -> Self
625    {
626        self.time_nsec = 0;
627
628        return self;
629    }
630}
631
632/// A trait which is implemented by [TimerExpMode] for each of the time
633/// types i.e [AbsoluteTime] and [RelativeTime] and provides an interface 
634/// for the methods to check the instance and set flags. Also, in case if
635/// this trait would be implemented on the custom struct the instance 
636/// should be convertable [Into] [itimerspec].
637pub trait TimerExpModeInto: Into<itimerspec> 
638{
639    /// Verifies that the instance contains a valid values.
640    /// 
641    /// For `absolute` time, it should not be zero.
642    fn is_valid(&self) -> bool;
643
644    /// Should return the flags for the timer which corresponds the timer type.
645    fn get_flags(&self) -> TimerSetTimeFlags;
646}
647
648
649
650/// A timer expiry modes. Not every OS supports 
651/// every mode. Read comments for the OS specific
652/// timer. For the `nanoseconds` param the max value
653/// is 999_999_999 for most OSes.
654#[derive(Clone, Copy, Debug, PartialEq, Eq)]
655pub enum TimerExpMode<TIMERTYPE: ModeTimeType>
656{
657    /// Disarmed
658    None, 
659
660    /// A timer which is triggered once.
661    OneShot
662    {
663        timeout: TIMERTYPE
664    },
665    
666    /// Interval with the initial delay.
667    IntervalDelayed
668    {
669        /// First event delay.
670        delay_tm: TIMERTYPE,
671
672        /// Interval.
673        interv_tm: TIMERTYPE
674    },
675
676    /// Interval, with the first timeout event 
677    /// equal to interval values.
678    Interval
679    {
680        /// Interval seconds.
681        interv_tm: TIMERTYPE
682    },
683}
684
685
686impl ops::AddAssign<RelativeTime> for TimerExpMode<AbsoluteTime>
687{
688    fn add_assign(&mut self, rhs: RelativeTime) 
689    {
690        match self
691        {
692            TimerExpMode::None => 
693                return,
694            TimerExpMode::OneShot { timeout } => 
695            {
696                *timeout += rhs;
697                
698            },
699            TimerExpMode::IntervalDelayed { interv_tm, .. } => 
700            {
701                *interv_tm += rhs;
702            },
703            TimerExpMode::Interval { interv_tm } => 
704            {
705               *interv_tm += rhs;
706            },
707        }
708    }
709}
710
711
712impl ops::Add<RelativeTime> for TimerExpMode<AbsoluteTime>
713{
714    type Output = TimerExpMode<AbsoluteTime>;
715
716    fn add(mut self, rhs: RelativeTime) -> Self::Output 
717    {
718        self += rhs;
719
720        return self;
721    }
722}
723
724
725impl<TIMERTYPE: ModeTimeType> Ord for TimerExpMode<TIMERTYPE>
726{
727    fn cmp(&self, other: &Self) -> Ordering 
728    {
729        match (self, other)
730        {
731            (TimerExpMode::None, TimerExpMode::None) => 
732                return Ordering::Equal,
733            (TimerExpMode::OneShot{ timeout }, TimerExpMode::OneShot { timeout: timeout2 }) => 
734            { 
735                return timeout.cmp(timeout2);
736            },
737            (
738                TimerExpMode::IntervalDelayed{ delay_tm, interv_tm }, 
739                TimerExpMode::IntervalDelayed{ delay_tm: delay_tm2, interv_tm: interv_tm2 }
740            ) =>
741            {
742                return 
743                    delay_tm.cmp(delay_tm2)
744                        .then(interv_tm.cmp(interv_tm2));
745            },
746            (TimerExpMode::Interval { interv_tm }, TimerExpMode::Interval { interv_tm: interv_tm2 }) => 
747            {
748                return interv_tm.cmp(interv_tm2);
749            },
750            _ => 
751                panic!("cannot compare different types {} and {}", self, other)
752        }
753    }
754}
755
756impl<TIMERTYPE: ModeTimeType> PartialOrd for TimerExpMode<TIMERTYPE>
757{
758    fn partial_cmp(&self, other: &Self) -> Option<Ordering> 
759    {
760        return Some(self.cmp(other));
761    }
762}
763
764impl TimerExpModeInto for TimerExpMode<AbsoluteTime>
765{
766    #[inline]
767    fn is_valid(&self) -> bool
768    {
769        return self.is_valid_inner();
770    }
771
772    #[inline]
773    fn get_flags(&self) -> TimerSetTimeFlags
774    {
775        return AbsoluteTime::get_flags();
776    }
777}
778
779/// Implementations of the [TimerExpMode] for [AbsoluteTime].
780impl TimerExpMode<AbsoluteTime>
781{
782    /// Checks value for the `set_time` function. To disarm timer 
783    /// use `unset_time`.
784    #[inline]
785    fn is_valid_inner(&self) -> bool
786    {
787        match self
788        {
789            Self::None => 
790                return false,
791            Self::OneShot{ timeout} => 
792                return timeout.is_value_valid(),
793            Self::IntervalDelayed{ delay_tm, interv_tm } => 
794                return delay_tm.is_value_valid() && interv_tm.is_value_valid(),
795            Self::Interval{ interv_tm } => 
796                return interv_tm.is_value_valid()
797        }
798    }
799
800    /// Construct the [TimerExpMode::OneShot] timer. For the `absolute` timer
801    /// only this type is available. The [AbsoluteTime] should be provided which
802    /// should be ahead of the OS'es timer.
803    pub 
804    fn new_oneshot(abs_time: AbsoluteTime) -> Self
805    {
806        return Self::OneShot { timeout: abs_time };
807    }
808}
809
810impl TimerExpModeInto for TimerExpMode<RelativeTime>
811{
812    #[inline]
813    fn is_valid(&self) -> bool
814    {
815        return true;
816    }
817
818    #[inline]
819    fn get_flags(&self) -> TimerSetTimeFlags
820    {
821        return RelativeTime::get_flags();
822    }
823}
824
825/// Implementations of the [TimerExpMode] for [RelativeTime].
826impl TimerExpMode<RelativeTime>
827{
828    /// Construct the [TimerExpMode::OneShot] timer. A [RelativeTime] should 
829    /// be provided as argument. This type of timer is triggered only once.
830    pub 
831    fn new_oneshot(rel_time: RelativeTime) -> Self
832    {
833        return Self::OneShot { timeout: rel_time };
834    }
835
836    /// Constrcut the [TimerExpMode::Interval] timer. A [RelativeTime] should 
837    /// be provided as agument which specifies the trigger interval.
838    pub 
839    fn new_interval(rel_time: RelativeTime) -> Self
840    {
841        return Self::Interval { interv_tm: rel_time };
842    }
843
844    /// Construct the [TimerExpMode::IntervalDelayed] timer. A two [RelativeTime] 
845    /// arguments should be provided which would set the initial delay and further
846    /// interval. The initial delay happens only once. Then the interval will be used.
847    /// If `delay_time` and `intev_time` are same, acts as `new_interval`.
848    pub 
849    fn new_interval_with_init_delay(delay_time: RelativeTime, intev_time: RelativeTime) -> Self
850    {
851        return Self::IntervalDelayed { delay_tm: delay_time, interv_tm: intev_time };
852    }
853}
854
855impl<TIMERTYPE: ModeTimeType> TimerExpMode<TIMERTYPE>
856{
857    /// Disarms the timer.
858    #[inline]
859    pub 
860    fn reset() -> Self
861    {
862        return Self::None;
863    }
864}
865
866impl<TIMERTYPE: ModeTimeType> fmt::Display for TimerExpMode<TIMERTYPE>
867{
868    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
869    {
870        match self
871        {
872            Self::None => 
873                write!(f, "disarmed"),
874            Self::OneShot{ timeout } => 
875                write!(f, "oneshot {}", timeout),
876            Self::IntervalDelayed
877                { delay_tm, interv_tm } => 
878                write!(f, "interval {} with delay {}", interv_tm, delay_tm),
879            Self::Interval{ interv_tm } => 
880                write!(f, "interval {}", interv_tm),
881        }
882    }
883}
884
885#[cfg(any(
886    target_os = "freebsd",
887    target_os = "dragonfly",
888    target_os = "netbsd",
889    target_os = "openbsd",
890    target_os = "macos",
891    target_os = "linux",
892))]
893use nix::libc::{itimerspec, timespec};
894
895#[cfg(target_os = "macos")]
896#[repr(C)]
897pub struct timespec 
898{
899    pub tv_sec: libc::time_t,
900    pub tv_nsec: libc::c_long,
901}
902#[cfg(target_os = "macos")]
903#[repr(C)]
904pub struct itimerspec 
905{
906    pub it_interval: timespec,
907    pub it_value: timespec,
908}
909
910
911/// Converts from [itimerspec] into [TimerExpMode] of the `TIMERTYPE`.
912impl<TIMERTYPE: ModeTimeType> From<itimerspec> for TimerExpMode<TIMERTYPE>
913{
914    fn from(value: itimerspec) -> Self 
915    {
916        if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0 &&
917            value.it_value.tv_sec == 0 && value.it_value.tv_nsec == 0
918        {
919            // unset
920            return Self::None;
921        }
922        else if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0
923        {
924            // one shot
925            return 
926                Self::OneShot
927                { 
928                    timeout: TIMERTYPE::new(value.it_value.tv_sec, value.it_value.tv_nsec) 
929                };
930        }
931        else if value.it_interval.tv_sec == value.it_value.tv_sec &&
932            value.it_interval.tv_nsec == value.it_value.tv_nsec
933        {
934            // interval
935            return 
936                Self::Interval
937                { 
938                    interv_tm: TIMERTYPE::new(value.it_interval.tv_sec, value.it_interval.tv_nsec) 
939                };
940        }
941        else
942        {
943            // delayed interval
944            return 
945                Self::IntervalDelayed 
946                { 
947                    delay_tm: TIMERTYPE::new(value.it_value.tv_sec, value.it_value.tv_nsec) ,
948                    interv_tm: TIMERTYPE::new(value.it_interval.tv_sec, value.it_interval.tv_nsec) 
949                };
950        }
951    }
952}
953
954impl<TIMERTYPE: ModeTimeType> From<TimerExpMode<TIMERTYPE>> for itimerspec
955{
956    fn from(value: TimerExpMode<TIMERTYPE>) -> Self 
957    {
958        return (&value).into();
959    }
960}
961
962/// Converts from the reference to [TimerExpMode] of the `TIMERTYPE` into the 
963/// [itimerspec].
964impl<TIMERTYPE: ModeTimeType> From<&TimerExpMode<TIMERTYPE>> for itimerspec
965{
966    fn from(value: &TimerExpMode<TIMERTYPE>) -> Self 
967    {
968        match value
969        {
970            TimerExpMode::None => 
971                return 
972                    itimerspec 
973                    {
974                        it_interval: timespec 
975                        {
976                            tv_sec: 0,
977                            tv_nsec: 0,
978                        },
979                        it_value: timespec
980                        {
981                            tv_sec: 0,
982                            tv_nsec: 0,
983                        },
984                    },
985            TimerExpMode::OneShot{ timeout} =>
986                return 
987                    itimerspec 
988                    {
989                        it_interval: timespec 
990                        {
991                            tv_sec: 0,
992                            tv_nsec: 0,
993                        },
994                        it_value: timespec
995                        {
996                            tv_sec: timeout.get_sec(),
997                            tv_nsec: timeout.get_nsec(),
998                        },
999                    },
1000            TimerExpMode::IntervalDelayed{ delay_tm, interv_tm } => 
1001                return 
1002                    itimerspec 
1003                    {
1004                        it_interval: timespec 
1005                        {
1006                            tv_sec: interv_tm.get_sec(),
1007                            tv_nsec: interv_tm.get_nsec(),
1008                        },
1009                        it_value: timespec
1010                        {
1011                            tv_sec: delay_tm.get_sec(),
1012                            tv_nsec: delay_tm.get_nsec(),
1013                        },
1014                    },
1015            TimerExpMode::Interval{ interv_tm } => 
1016                return 
1017                    itimerspec 
1018                    {
1019                        it_interval: timespec 
1020                        {
1021                            tv_sec: interv_tm.get_sec(),
1022                            tv_nsec: interv_tm.get_nsec(),
1023                        },
1024                        it_value: timespec
1025                        {
1026                            tv_sec: interv_tm.get_sec(),
1027                            tv_nsec: interv_tm.get_nsec(),
1028                        },
1029                    }
1030        }
1031    }
1032}
1033
1034/// A timer FD read operation result.
1035#[derive(Debug, Clone, PartialEq, Eq)]
1036pub enum TimerReadRes<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq>
1037{
1038    /// Read successfull.
1039    Ok(T),
1040
1041    /// TFD_TIMER_ABSTIME 
1042    /// > Marks this timer as cancelable if the real-time clock  under‐
1043    /// > goes  a  discontinuous change (settimeofday(2), clock_settime(2),
1044    /// > or similar).  When  such  changes  occur,  a  current  or  future
1045    /// > read(2)  from  the file descriptor will fail with the error 
1046    /// > ECANCELED.
1047    Cancelled,
1048
1049    /// EAGAIN
1050    /// If FD is nonblocking then this will be returned.
1051    WouldBlock,
1052}
1053
1054impl TimerReadRes<u64>
1055{
1056    pub 
1057    fn ok() -> Self
1058    {
1059        return Self::Ok(1);
1060    }
1061}
1062
1063impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> From<io::Error> for TimerReadRes<T>
1064{
1065    fn from(value: io::Error) -> Self 
1066    {
1067        if let Some(errn) = value.raw_os_error()
1068        {
1069            if errn == ECANCELED
1070            {
1071                return Self::Cancelled;
1072            }
1073            else if errn == EWOULDBLOCK
1074            {
1075                return Self::WouldBlock;
1076            }
1077        }
1078
1079        return Self::Cancelled;
1080    }
1081}
1082
1083impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> fmt::Display for TimerReadRes<T>
1084{
1085    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1086    {
1087        match self
1088        {
1089            Self::Ok(ovfl) => 
1090                write!(f, "OK(overflows:{})", ovfl),
1091            Self::Cancelled => 
1092                write!(f, "CANCELLED"),
1093            Self::WouldBlock => 
1094                write!(f, "WOULDBLOCK"),
1095        }
1096    }
1097}
1098
1099impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> TimerReadRes<T>
1100{
1101    pub 
1102    fn unwrap(self) -> T
1103    {
1104        let Self::Ok(t) = self
1105        else { panic!("can not unwrap {:?}", self)};
1106
1107        return t;
1108    }
1109}
1110
1111/// A common trait which is implemented by all timer realizationss for different OSes.
1112pub trait FdTimerCom
1113{
1114    /// Creates new isntance of the timer.
1115    /// 
1116    /// # Arguments
1117    /// 
1118    /// * `label` - a [Cow] string which defines a title of the timer for identification.
1119    /// 
1120    /// * `timer_type` - a [TimerType] a clock source
1121    /// 
1122    /// * `timer_flags` - a [TimerFlags] configuration of the timer's FD.
1123    /// 
1124    /// # Returns
1125    /// 
1126    /// A [Result] is retuned with instance on success.
1127    fn new(label: Cow<'static, str>, timer_type: TimerType, timer_flags: TimerFlags) -> TimerPortResult<Self>
1128    where Self: Sized;
1129
1130    /// Attempts to read the timer. The realization is different on different OS. The main purpose 
1131    /// is to check if timer is ready (ended).
1132    fn read(&self) -> TimerPortResult<TimerReadRes<u64>>;
1133
1134    /// The same as `read` but the buffer is external. The amount of read bytes are returned as
1135    /// a result.
1136    fn read_buf(&self, unfilled: &mut [u8]) -> std::io::Result<usize>;
1137
1138    /// Sets the timer. The timer starts immidiatly.
1139    fn set_time<TIMERTYPE: TimerExpModeInto>(&self, timer_exp: TIMERTYPE) -> TimerPortResult<()>;
1140
1141    /// Unsets the timer. The timer stops immidiatly.
1142    fn unset_time<TIMERTYPE: ModeTimeType>(&self) -> TimerPortResult<()>;
1143}
1144
1145
1146#[cfg(test)]
1147mod tests
1148{
1149
1150    use crate::{common, timer_portable::timer::{AbsoluteTime, ModeTimeType, RelativeTime, TimerExpMode}};
1151
1152    #[test]
1153    fn test_0() 
1154    {
1155        let ts = common::get_current_timestamp();
1156
1157        let texp1 = TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1158
1159        assert_eq!(
1160            TimerExpMode::OneShot { timeout: AbsoluteTime::from(ts) },
1161            texp1
1162        );
1163        
1164    }
1165
1166    #[test]
1167    fn test_1() 
1168    {
1169        let ts = common::get_current_timestamp();
1170
1171        let texp1 = 
1172            TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1173
1174        let texp2 = 
1175            texp1 + RelativeTime::new_time(1, 0);
1176
1177        assert_eq!(texp1 < texp2, true);
1178        assert_eq!(texp2 > texp1, true);
1179        assert_eq!(texp2 != texp1, true);
1180        assert_eq!(texp2 < texp1, false);
1181    }
1182
1183    #[test]
1184    fn test_2() 
1185    {
1186
1187        let texp1 = 
1188            TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::new(100, AbsoluteTime::MAX_NS));
1189       
1190        let texp2 = 
1191            texp1 + RelativeTime::new_time(0, 1);
1192
1193
1194        assert_eq!(texp1 < texp2, true);
1195        assert_eq!(texp2 > texp1, true);
1196        assert_eq!(texp2 != texp1, true);
1197        assert_eq!(texp2 < texp1, false);
1198    }
1199
1200    #[should_panic]
1201    #[test]
1202    fn test_2_fail() 
1203    {
1204        let ts = common::get_current_timestamp();
1205
1206        let texp1 = 
1207            TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1208
1209        let texp2 = 
1210            TimerExpMode::<AbsoluteTime>::Interval { interv_tm:  AbsoluteTime::from(ts)};
1211
1212        assert_eq!(texp1 == texp2, true);
1213    }
1214
1215    #[test]
1216    fn test_abstime_cmp()
1217    {
1218        let abs_time = AbsoluteTime::now();
1219        let abs_time_future = abs_time + RelativeTime::new_time(10, 1);
1220        let abs_time_past = abs_time - RelativeTime::new_time(10, 1);
1221
1222        assert_eq!(abs_time < abs_time_future, true);
1223        assert_eq!(abs_time_future > abs_time, true);
1224        assert_eq!(abs_time > abs_time_past, true);
1225        assert_eq!(abs_time_past < abs_time, true);
1226        assert_eq!(abs_time_future > abs_time_past, true);
1227        assert_eq!(abs_time_past < abs_time_future, true);
1228    }
1229
1230    #[test]
1231    fn test_abstime_new()
1232    {
1233        let abs = AbsoluteTime::new_time(1, 999_999_999);
1234        assert_eq!(abs.time_nsec, 999_999_999);
1235        assert_eq!(abs.time_sec, 1);
1236
1237        let abs = AbsoluteTime::new_time(1, 1_000_000_000);
1238        assert_eq!(abs.time_nsec, 0);
1239        assert_eq!(abs.time_sec, 2);
1240
1241        let abs = AbsoluteTime::new_time(1, 1_000_000_001);
1242        assert_eq!(abs.time_nsec, 1);
1243        assert_eq!(abs.time_sec, 2);
1244
1245        let abs = AbsoluteTime::new_time(1, 2_000_000_001);
1246        assert_eq!(abs.time_nsec, 1);
1247        assert_eq!(abs.time_sec, 3);
1248    }
1249
1250    #[test]
1251    fn test_abstime_add()
1252    {
1253        let mut abs = AbsoluteTime::new_time(1, 999_999_999);
1254
1255        abs += RelativeTime::new_time(0, 1);
1256
1257        assert_eq!(abs.time_nsec, 0);
1258        assert_eq!(abs.time_sec, 2);
1259
1260        abs += RelativeTime::new_time(1, 1);
1261
1262        assert_eq!(abs.time_nsec, 1);
1263        assert_eq!(abs.time_sec, 3);
1264
1265        abs += RelativeTime::new_time(0, 999_999_999);
1266
1267        assert_eq!(abs.time_nsec, 0);
1268        assert_eq!(abs.time_sec, 4);
1269
1270        abs -= RelativeTime::new_time(0, 999_999_999);
1271
1272        assert_eq!(abs.time_nsec, 1);
1273        assert_eq!(abs.time_sec, 3);
1274
1275        abs -= RelativeTime::new_time(0, 1);
1276
1277        assert_eq!(abs.time_nsec, 0);
1278        assert_eq!(abs.time_sec, 3);
1279
1280        abs -= RelativeTime::new_time(0, 500_000_000);
1281
1282        assert_eq!(abs.time_nsec, 500_000_000);
1283        assert_eq!(abs.time_sec, 2);
1284
1285        abs -= RelativeTime::new_time(0, 400_000_000);
1286
1287        assert_eq!(abs.time_nsec, 100_000_000);
1288        assert_eq!(abs.time_sec, 2);
1289
1290        abs -= RelativeTime::new_time(1, 200_000_000);
1291
1292        assert_eq!(abs.time_nsec, 900_000_000);
1293        assert_eq!(abs.time_sec, 0);
1294    }
1295}