use std::{cell::Cell, fmt, marker::PhantomData, rc, task::Waker};
#[derive(Default)]
pub struct LocalWaker {
waker: Cell<Option<Waker>>,
_t: PhantomData<rc::Rc<()>>,
}
impl LocalWaker {
pub fn new() -> Self {
LocalWaker {
waker: Cell::new(None),
_t: PhantomData,
}
}
pub fn with(waker: Option<Waker>) -> Self {
LocalWaker {
waker: Cell::new(waker),
_t: PhantomData,
}
}
#[inline]
pub fn register(&self, waker: &Waker) -> bool {
self.waker.replace(Some(waker.clone())).is_some()
}
#[inline]
pub fn wake(&self) {
if let Some(waker) = self.take() {
waker.wake();
}
}
#[inline]
pub fn wake_checked(&self) -> bool {
if let Some(waker) = self.take() {
waker.wake();
true
} else {
false
}
}
pub fn take(&self) -> Option<Waker> {
self.waker.take()
}
}
impl Clone for LocalWaker {
fn clone(&self) -> Self {
LocalWaker::new()
}
}
impl fmt::Debug for LocalWaker {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LocalWaker")
}
}
pub async fn yield_to() {
use std::{future::Future, pin::Pin, task::Context, task::Poll};
struct Yield {
completed: bool,
}
impl Future for Yield {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if self.completed {
return Poll::Ready(());
}
self.completed = true;
cx.waker().wake_by_ref();
Poll::Pending
}
}
Yield { completed: false }.await;
}
#[cfg(test)]
mod test {
use super::*;
#[ntex_macros::rt_test2]
async fn yield_test() {
yield_to().await;
}
}