#[cfg(
any(
target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "openbsd",
target_os = "macos",
)
)
]
pub mod bsd;
#[cfg(target_os = "linux")]
pub mod linux;
use std::{fmt, io};
pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
pub use nix::libc::{self, ECANCELED, EWOULDBLOCK};
#[cfg(target_os = "linux")]
pub use linux::timer_poll::TimerEventWatch;
#[cfg(
any(
target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "openbsd",
target_os = "macos",
)
)]
pub use bsd::TimerEventWatch;
#[cfg(target_os = "linux")]
pub use linux::timer_fd_linux::TimerFdInternal;
use crate::{AbsoluteTime, RelativeTime, TimerFd, TimerReadRes, timer_portable::{TimerExpMode, TimerId, timer::ModeTimeType}};
#[cfg(
all(
any(
target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "openbsd",
target_os = "macos",
),
feature = "bsd_use_timerfd"
)
)]
pub use bsd::timer_fd_bsd::TimerFdInternal;
#[cfg(
all(
any(
target_os = "freebsd",
target_os = "dragonfly",
target_os = "netbsd",
target_os = "openbsd",
target_os = "macos",
),
not(feature = "bsd_use_timerfd")
)
)]
pub use bsd::timer_kqueue_fd_bsd::TimerFdInternal;
use bitflags::bitflags;
#[allow(non_camel_case_types)]
#[repr(i32)]
#[derive(Debug)]
pub enum TimerType
{
CLOCK_REALTIME = libc::CLOCK_REALTIME,
CLOCK_MONOTONIC = libc::CLOCK_MONOTONIC,
#[cfg(target_os = "linux")]
CLOCK_BOOTTIME = libc::CLOCK_BOOTTIME,
#[cfg(target_os = "linux")]
CLOCK_REALTIME_ALARM = libc::CLOCK_REALTIME_ALARM,
#[cfg(target_os = "linux")]
CLOCK_BOOTTIME_ALARM = libc::CLOCK_BOOTTIME_ALARM,
}
impl From<TimerType> for libc::clockid_t
{
fn from(value: TimerType) -> Self
{
return value as libc::clockid_t;
}
}
bitflags! {
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct TimerFlags: i32
{
const TFD_NONBLOCK = libc::TFD_NONBLOCK;
const TFD_CLOEXEC = libc::TFD_CLOEXEC;
}
}
bitflags! {
#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
pub struct TimerSetTimeFlags: i32
{
const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET;
}
}
impl From<RawFd> for TimerId
{
fn from(value: RawFd) -> Self
{
return Self(value as usize);
}
}
impl From<u64> for TimerId
{
fn from(value: u64) -> Self
{
return Self(value as usize);
}
}
impl PartialEq<RawFd> for TimerId
{
fn eq(&self, other: &RawFd) -> bool
{
return self.0 == *other as usize;
}
}
pub trait UnixFd: AsFd + AsRawFd + PartialEq<RawFd> {}
impl UnixFd for TimerFd {}
impl PartialEq<RawFd> for TimerFd
{
fn eq(&self, other: &RawFd) -> bool
{
return self.as_raw_fd() == *other;
}
}
impl AsFd for TimerFd
{
fn as_fd(&self) -> BorrowedFd<'_>
{
return self.get_timer().as_fd();
}
}
impl AsRawFd for TimerFd
{
fn as_raw_fd(&self) -> RawFd
{
return self.get_timer().as_raw_fd();
}
}
pub use nix::libc::{itimerspec, timespec};
impl<TIMERTYPE: ModeTimeType> From<itimerspec> for TimerExpMode<TIMERTYPE>
{
fn from(value: itimerspec) -> Self
{
if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0 &&
value.it_value.tv_sec == 0 && value.it_value.tv_nsec == 0
{
return Self::None;
}
else if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0
{
return
Self::OneShot
{
timeout: TIMERTYPE::from(value.it_value)
};
}
else if value.it_interval.tv_sec == value.it_value.tv_sec &&
value.it_interval.tv_nsec == value.it_value.tv_nsec
{
return
Self::Interval
{
interv_tm: TIMERTYPE::from(value.it_interval)
};
}
else
{
return
Self::IntervalDelayed
{
delay_tm: TIMERTYPE::from(value.it_value),
interv_tm: TIMERTYPE::from(value.it_interval)
};
}
}
}
impl From<timespec> for RelativeTime
{
fn from(time_spec: timespec) -> Self
{
return
Self::new_time(time_spec.tv_sec, time_spec.tv_nsec);
}
}
impl From<timespec> for AbsoluteTime
{
fn from(time_spec: timespec) -> Self
{
return
unsafe
{
Self::new_time_unchecked(time_spec.tv_sec, time_spec.tv_nsec)
};
}
}
impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> From<io::Error> for TimerReadRes<T>
{
fn from(value: io::Error) -> Self
{
if let Some(errn) = value.raw_os_error()
{
if errn == ECANCELED
{
return Self::Cancelled;
}
else if errn == EWOULDBLOCK
{
return Self::WouldBlock;
}
}
return Self::Cancelled;
}
}
impl<TIMERTYPE: ModeTimeType> From<TimerExpMode<TIMERTYPE>> for itimerspec
{
fn from(value: TimerExpMode<TIMERTYPE>) -> Self
{
return (&value).into();
}
}
impl<TIMERTYPE: ModeTimeType> From<&TimerExpMode<TIMERTYPE>> for itimerspec
{
fn from(value: &TimerExpMode<TIMERTYPE>) -> Self
{
match value
{
TimerExpMode::None =>
return
itimerspec
{
it_interval: timespec
{
tv_sec: 0,
tv_nsec: 0,
},
it_value: timespec
{
tv_sec: 0,
tv_nsec: 0,
},
},
TimerExpMode::OneShot{ timeout} =>
return
itimerspec
{
it_interval: timespec
{
tv_sec: 0,
tv_nsec: 0,
},
it_value: timespec
{
tv_sec: timeout.get_sec(),
tv_nsec: timeout.get_nsec(),
},
},
TimerExpMode::IntervalDelayed{ delay_tm, interv_tm } =>
return
itimerspec
{
it_interval: timespec
{
tv_sec: interv_tm.get_sec(),
tv_nsec: interv_tm.get_nsec(),
},
it_value: timespec
{
tv_sec: delay_tm.get_sec(),
tv_nsec: delay_tm.get_nsec(),
},
},
TimerExpMode::Interval{ interv_tm } =>
return
itimerspec
{
it_interval: timespec
{
tv_sec: interv_tm.get_sec(),
tv_nsec: interv_tm.get_nsec(),
},
it_value: timespec
{
tv_sec: interv_tm.get_sec(),
tv_nsec: interv_tm.get_nsec(),
},
}
}
}
}
#[cfg(all(target_family = "unix", feature = "enable_mio_compat"))]
pub mod mio_compat
{
use std::{io, os::fd::{AsRawFd, RawFd}};
use mio::{Token, unix::SourceFd};
use crate::timer_portable::timer::TimerFdMioCompat;
use super::TimerFd;
impl mio::event::Source for TimerFd
{
fn register(
&mut self,
registry: &mio::Registry,
token: mio::Token,
interests: mio::Interest,
) -> io::Result<()>
{
return
SourceFd(&self.as_raw_fd()).register(registry, token, interests);
}
fn reregister(
&mut self,
registry: &mio::Registry,
token: mio::Token,
interests: mio::Interest,
) -> io::Result<()>
{
return
SourceFd(&self.as_raw_fd()).reregister(registry, token, interests);
}
fn deregister(&mut self, registry: &mio::Registry) -> io::Result<()>
{
return
SourceFd(&self.as_raw_fd()).deregister(registry)
}
}
impl PartialEq<Token> for TimerFd
{
fn eq(&self, other: &Token) -> bool
{
return self.as_raw_fd() == other.0 as RawFd;
}
}
impl TimerFdMioCompat for TimerFd
{
fn get_token(&self) -> Token
{
return Token(self.as_raw_fd() as usize);
}
}
}