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