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