timer-deque-rs 0.7.0

A OS based timer and timer queue which implements timeout queues of different types.
Documentation
/*-
 * timer-deque-rs - a Rust crate which provides timer and timer queues based on target OS
 *  functionality.
 * 
 * Copyright (C) 2025 Aleksandr Morozov alex@nixd.org
 *  4neko.org alex@4neko.org
 * 
 * The timer-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *                     
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */

use std::fmt;

use chrono::{DateTime, Local};


/// Returns the current [DateTime].
#[inline]
pub 
fn get_current_timestamp() -> DateTime<Local>
{
    return chrono::offset::Local::now();
}

/// The "sequenceId" parameter tracks the sequence in which the
/// originator submits messages to the syslog transport for sending.
#[cfg(target_has_atomic = "64")]
static ORD_ID: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0);

/// The "sequenceId" parameter tracks the sequence in which the
/// originator submits messages to the syslog transport for sending.
#[cfg(not(target_has_atomic = "64"))]
static ORD_ID: std::sync::Mutex<u32> = std::sync::Mutex::new(0);

/// A uniq ID which is generated for every ticket. It is a 128bit
/// value which consists from timestamp sec and ns and random number.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TimerDequeId
{
    /// seconds
    pub(crate) timestamp: i64,

    /// nanoseconds
    pub(crate) timestamp_ns: u32,

    /// random number
    pub(crate) ran_id: u32,
}


impl fmt::Display for TimerDequeId
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        write!(f, "{:X}/{:X}/{:X}", self.timestamp, self.timestamp_ns, self.ran_id)
    }
}

impl TimerDequeId
{
    #[cfg(target_has_atomic = "64")] 
    fn generate_ord_numer() -> u32
    {
        use std::sync::atomic::{Ordering};

        let mut last = ORD_ID.load(Ordering::Relaxed);
        
        loop 
        {
            let seq_id = 
                match last.checked_add(1) 
                {
                    Some(id) => id,
                    None =>
                    {
                        0
                    }
                };

            match ORD_ID.compare_exchange_weak(last, seq_id, Ordering::Relaxed, Ordering::Relaxed) 
            {
                Ok(_) => 
                    return seq_id,
                Err(id) => 
                    last = id,
            }
        }
    }

    #[cfg(not(target_has_atomic = "64"))]
    fn generate_sequence_num() -> u32
    {
        let mut seq_id_cnt = 
            ORD_ID.lock().unwrap_or_else(std::sync::PoisonError::into_inner);

        let seq_id = 
            match seq_id_cnt.checked_add(1) 
            {
                Some(id) => id,
                None =>
                {
                    0
                }
            };

        *seq_id_cnt = seq_id;
        drop(seq_id_cnt);

        return seq_id;
    }

    pub(crate) 
    fn new() -> Self
    {
        let ts = get_current_timestamp();
        let ord_num = Self::generate_ord_numer();

        return 
            Self
            { 
                timestamp: 
                    ts.timestamp(), 
                timestamp_ns: 
                    ts.timestamp_subsec_nanos(), 
                ran_id: 
                    ord_num, 
            }; 
    }
}