use core::cell::Cell;
use hicollections::{list, List, ListNode};
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "illumos",
target_os = "redox",
))] {
mod epoll;
pub use epoll::*;
} else if #[cfg(any(
target_os = "ios",
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "tvos",
target_os = "watchos",
))] {
mod kqueue;
pub use kqueue::*;
} else {
mod select;
pub use select::*;
}
}
mod scheduler;
pub use scheduler::*;
mod waker;
pub(crate) use waker::*;
mod timer;
pub use timer::*;
#[repr(C)]
pub struct Event {
pub(crate) node: ListNode,
events: Cell<u32>,
handle: fn(&Event, u32, &mut Scheduler),
}
pub fn event_list_new() -> List<Event> {
list!(Event, node)
}
impl Event {
pub fn new(handle: fn(&Event, u32, &mut Scheduler)) -> Self {
Self {
node: ListNode::new(),
events: Cell::new(0),
handle,
}
}
pub fn handle(&self, event: u32, sched: &mut Scheduler) {
(self.handle)(self, event, sched)
}
}
#[cfg(test)]
mod test {
use crate::event::{self, Scheduler};
use core::ptr;
use hipool::MemPool;
#[test]
fn test_waker() {
let pool = MemPool::new_boxed(0).unwrap();
let mut poll = event::Poll::new_in(unsafe { &*pool.as_ptr() }).unwrap();
let waker = event::Waker::new().unwrap();
let _ = poll.add_event(waker.fd, event::POLLIN, ptr::null::<event::Event>());
let mut events = 0;
let n = poll
.wait(0, |e, _| {
events = e;
})
.unwrap();
assert_eq!(events, 0);
assert_eq!(n, 0);
assert!(!waker.awaken());
waker.wake();
let n = poll
.wait(0, |e, _| {
events = e;
})
.unwrap();
assert_eq!(n, 1);
assert!(waker.awaken());
}
#[test]
fn test_scheduler() {
let pool = MemPool::new_boxed(0).unwrap();
let mut sched = event::Scheduler::new_in(unsafe { &*pool.as_ptr() }).unwrap();
fn timer_timeout(this: &event::Timer, sched: &mut Scheduler) {
static mut STOP: i32 = 0;
if unsafe { STOP } == 0 {
unsafe { STOP = 1 };
unsafe { sched.set_timer(this, 1000000) };
} else {
sched.stop();
}
}
let timer = event::Timer::new(timer_timeout);
let now = sched.now();
unsafe { sched.set_timer(&timer, 1 * 1000 * 1000) };
sched.run();
assert!(sched.stopped());
let cur = sched.now();
assert!((cur - now).as_micros() >= 2 * 1000 * 1000);
}
}