use crate::{
RuntimeError,
constants::WAKE_IDENT,
modules::event_desc::EventDesc,
modules::{
int_check::IntCheck,
kevent::{KEvent, eventlist},
wake_target::WakeTarget,
},
};
use std::{ptr, sync::mpsc::Sender, thread};
pub(crate) struct Reactor;
impl Reactor {
pub(crate) fn init(id: i32, tx: Sender<i32>) {
reactor_loop(id, tx);
}
}
#[inline(always)]
fn reactor_loop(id: i32, tx: Sender<i32>) {
thread::spawn(move || {
let mut events = eventlist();
loop {
let count = match unsafe { KEvent::listen(id, &mut events) }.check() {
Ok(count) => count as usize,
Err(RuntimeError::CheckError(Some(libc::EINTR))) => continue,
Err(_) => break,
};
for event in events.iter().take(count) {
if event.flags & libc::EV_ERROR != 0 {
continue;
}
match WakeTarget::decode(event.udata) {
WakeTarget::None => continue,
WakeTarget::Queue(queue) => {
let _ = unsafe {
KEvent::register(
queue,
WAKE_IDENT,
0,
ptr::null_mut(),
EventDesc::new_user_trigger(),
)
}
.check();
}
WakeTarget::Parked(waiter) => unsafe { (*waiter).wake() },
}
}
}
let _ = tx.send(id);
});
}