1
0
Fork 0
forked from wry/wry

autocommit 2022-04-10 18:26:13 CEST

This commit is contained in:
Julian Orth 2022-04-10 18:26:13 +02:00
parent af152f7f3e
commit 6b3316e920
26 changed files with 514 additions and 82 deletions

View file

@ -3,11 +3,12 @@ pub use {
fd::{AsyncFd, FdStatus},
task::SpawnedFuture,
timeout::Timeout,
timer::Timer,
};
use {
crate::{
event_loop::{EventLoop, EventLoopError},
utils::{copyhashmap::CopyHashMap, numcell::NumCell},
utils::{copyhashmap::CopyHashMap, numcell::NumCell, oserror::OsError},
wheel::{Wheel, WheelError},
},
fd::AsyncFdData,
@ -19,15 +20,21 @@ use {
},
thiserror::Error,
timeout::TimeoutData,
uapi::OwnedFd,
uapi::{c, OwnedFd},
};
#[derive(Debug, Error)]
pub enum AsyncError {
#[error("The timer wheel returned an error: {0}")]
#[error("The timer wheel returned an error")]
WheelError(#[from] WheelError),
#[error("The event loop caused an error: {0}")]
#[error("The event loop caused an error")]
EventLoopError(#[from] EventLoopError),
#[error("Could not read from a timer")]
TimerReadError(#[source] OsError),
#[error("Could not set a timer")]
SetTimer(#[source] OsError),
#[error("Could not create a timer")]
CreateTimer(#[source] OsError),
}
#[derive(Copy, Clone, Eq, PartialEq)]
@ -71,6 +78,10 @@ impl AsyncEngine {
})
}
pub fn timer(self: &Rc<Self>, clock_id: c::c_int) -> Result<Timer, AsyncError> {
Timer::new(self, clock_id)
}
pub fn spawn<T, F: Future<Output = T> + 'static>(&self, f: F) -> SpawnedFuture<T> {
self.queue.spawn(Phase::EventHandling, f)
}
@ -146,6 +157,59 @@ mod yield_ {
}
}
mod timer {
use {
crate::async_engine::{AsyncEngine, AsyncError, AsyncFd},
std::{rc::Rc, time::Duration},
uapi::c,
};
#[derive(Clone)]
pub struct Timer {
fd: AsyncFd,
}
impl Timer {
pub(super) fn new(eng: &Rc<AsyncEngine>, clock_id: c::c_int) -> Result<Self, AsyncError> {
let fd = match uapi::timerfd_create(clock_id, c::TFD_CLOEXEC | c::TFD_NONBLOCK) {
Ok(fd) => fd,
Err(e) => return Err(AsyncError::CreateTimer(e.into())),
};
let afd = eng.fd(&Rc::new(fd))?;
Ok(Self { fd: afd })
}
pub async fn expired(&self) -> Result<u64, AsyncError> {
self.fd.readable().await?;
let mut buf = 0u64;
if let Err(e) = uapi::read(self.fd.raw(), &mut buf) {
return Err(AsyncError::TimerReadError(e.into()));
}
Ok(buf)
}
pub fn program(
&self,
initial: Option<Duration>,
periodic: Option<Duration>,
) -> Result<(), AsyncError> {
let mut timerspec: c::itimerspec = uapi::pod_zeroed();
if let Some(init) = initial {
timerspec.it_value.tv_sec = init.as_secs() as _;
timerspec.it_value.tv_nsec = init.subsec_nanos() as _;
if let Some(per) = periodic {
timerspec.it_interval.tv_sec = per.as_secs() as _;
timerspec.it_interval.tv_nsec = per.subsec_nanos() as _;
}
}
if let Err(e) = uapi::timerfd_settime(self.fd.raw(), 0, &timerspec) {
return Err(AsyncError::SetTimer(e.into()));
}
Ok(())
}
}
}
mod timeout {
use {
crate::wheel::{Wheel, WheelDispatcher, WheelId},