use crate::WakerEntity;
use ach_linked::LinkedList;
pub use ach_linked::Node;
pub struct WakerList<T> {
list: LinkedList<WakerEntity<T>>,
}
impl<T> WakerList<T> {
pub const fn new() -> Self {
Self {
list: LinkedList::new(),
}
}
pub unsafe fn register(&self, waker: &mut Node<WakerEntity<T>>) {
self.list.push(waker)
}
pub fn remove(&self, waker: &mut Node<WakerEntity<T>>) {
self.list.remove(waker)
}
pub fn wake_one(&self) -> bool {
if let Some(list) = self.list.take_all() {
let mut waker = unsafe { &mut *(list as *mut Node<WakerEntity<T>>) };
let ret = loop {
if waker.wake() {
break true;
} else {
if let Some(list) = waker.next() {
waker = list
} else {
break false;
}
}
};
unsafe { self.list.push_list(list) };
ret
} else {
false
}
}
pub fn wake_all(&self) -> usize {
let mut num = 0;
if let Some(list) = self.list.take_all() {
let mut waker = unsafe { &mut *(list as *mut Node<WakerEntity<T>>) };
loop {
if waker.wake() {
num += 1;
}
if let Some(list) = waker.next() {
waker = list
} else {
break;
}
}
unsafe { self.list.push_list(list) };
}
num
}
pub fn retain(&self, mut f: impl FnMut(&WakerEntity<T>) -> bool) {
let list = self.list.take_all();
if let Some(list) = list {
let mut remain: Option<&mut Node<WakerEntity<T>>> = None;
for waker in list.into_iter() {
if f(&*waker) {
if let Some(remain) = &mut remain {
unsafe { remain.push(waker) };
} else {
remain = Some(waker);
}
}
}
if let Some(remain) = remain {
unsafe { self.list.push_list(remain) };
}
}
}
}