timer_deque_rs/timer_portable/
timer.rs

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