use core::{
convert::Infallible,
future::Future,
pin::Pin,
task::{Context, Poll, Waker},
};
use smallvec::SmallVec;
use crate::component::Component;
use super::FlowEntity;
pub struct YieldNow {
yielded: bool,
}
impl Default for YieldNow {
fn default() -> Self {
Self::new()
}
}
impl YieldNow {
pub const fn new() -> Self {
YieldNow { yielded: false }
}
}
impl Future for YieldNow {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.get_mut();
if !me.yielded {
me.yielded = true;
cx.waker().wake_by_ref();
Poll::Pending
} else {
Poll::Ready(())
}
}
}
#[macro_export]
macro_rules! yield_now {
() => {
$crate::flow::YieldNow::new().await
};
}
pub struct WakeOnDrop {
wakers: SmallVec<[Waker; 4]>,
}
impl Default for WakeOnDrop {
fn default() -> Self {
Self::new()
}
}
impl WakeOnDrop {
pub fn new() -> Self {
WakeOnDrop {
wakers: SmallVec::new(),
}
}
pub fn add_waker(&mut self, waker: &Waker) {
for elem in &mut self.wakers {
if elem.will_wake(waker) {
return;
}
}
self.wakers.push(waker.clone());
}
pub fn remove_waker(&mut self, waker: &Waker) {
if let Some(idx) = self.wakers.iter().position(|elem| elem.will_wake(waker)) {
self.wakers.swap_remove(idx);
}
}
}
impl Drop for WakeOnDrop {
fn drop(&mut self) {
for waker in self.wakers.drain(..) {
waker.wake();
}
}
}
impl Component for WakeOnDrop {
#[inline]
fn name() -> &'static str {
"WakeOnDrop"
}
}
impl FlowEntity {
pub async fn wait_despawned(self) {
let r = self
.try_poll(|_e, _cx| {
Poll::<Infallible>::Pending })
.await;
if let Ok(never) = r {
match never {}
}
}
pub async fn wait_has_component<T>(self)
where
T: 'static,
{
self.poll_view::<&T, _, _>(|_, _cx| Poll::Ready(())).await;
}
}