#![cfg_attr(not(feature = "std"), no_std)]
mod atomic;
mod yielder;
mod base;
#[cfg(feature = "std")]
mod asyncstd;
pub use base::event::EventSetter;
pub use yielder::Yield;
#[cfg(feature = "std")]
pub use asyncstd::{Event, EventAwait, CountedAwaiter, CountedEvent, LocalEvent, LocalEventAwait};
#[cfg(all(test, feature = "std"))]
mod tests {
use core::pin::pin;
use std::{
sync::Arc, task::{Context, Wake, Waker}
};
use crate::{asyncstd::{CountedEvent, Event}, base::event::EventSetter};
fn can_poll_immediate(fut: impl Future) -> bool {
let pinned = core::pin::pin!(fut);
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
pinned.poll(&mut ctx).is_ready()
}
fn setup_drop_cancel_test<'a>(event: &'a impl EventSetter<'a>) {
{
let mut waiter = core::pin::pin!(event.wait());
let waker = Waker::from(Arc::new(TestWaker {}));
let mut context = Context::from_waker(&waker);
assert!(waiter.as_mut().poll(&mut context).is_pending());
}
}
#[test]
pub fn test_shared_waker_correctness() {
let event_a = Event::new();
let event_b = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiting_a = core::pin::pin!(event_a.wait());
let mut waiting_b = core::pin::pin!(event_b.wait());
assert!(waiting_a.as_mut().poll(&mut ctx).is_pending());
assert!(waiting_b.as_mut().poll(&mut ctx).is_pending());
event_b.set_one();
assert!(waiting_a.as_mut().poll(&mut ctx).is_pending());
assert!(waiting_b.as_mut().poll(&mut ctx).is_ready());
assert!(waiting_a.as_mut().poll(&mut ctx).is_pending());
}
#[test]
pub fn test_waker_swap_correctness() {
let event = Event::new();
let waker_a = Waker::from(Arc::new(TestWaker {}));
let mut ctx_a = Context::from_waker(&waker_a);
let waker_b = Waker::from(Arc::new(TestWaker {}));
let mut ctx_b = Context::from_waker(&waker_b);
let mut waiting = core::pin::pin!(event.wait());
assert!(!event.has_waiters());
assert!(waiting.as_mut().poll(&mut ctx_a).is_pending());
assert!(event.has_waiters());
assert!(waiting.as_mut().poll(&mut ctx_b).is_pending());
}
#[test]
pub fn test_countable_correctness() {
let event = CountedEvent::new(Event::new());
assert_eq!(event.count(), 0);
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiting = core::pin::pin!(event.wait());
assert_eq!(event.count(), 0);
assert!(waiting.as_mut().poll(&mut ctx).is_pending());
assert_eq!(event.count(), 1);
event.set_one();
assert!(waiting.as_mut().poll(&mut ctx).is_ready());
assert_eq!(event.count(), 0);
}
#[test]
pub fn test_event_hotpath() {
let event = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
event.set_one();
assert!(core::pin::pin!(event.wait()).poll(&mut ctx).is_ready());
}
#[test]
pub fn test_event_hotpath_steal() {
let event = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiter = core::pin::pin!(event.wait());
assert!(waiter.as_mut().poll(&mut ctx).is_pending());
event.set_one();
assert!(pin!(event.wait()).poll(&mut ctx).is_pending());
assert!(waiter.as_mut().poll(&mut ctx).is_ready());
}
#[test]
pub fn event_has_waiter_with_priors() {
let event = Event::new();
assert!(!event.has_waiters());
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiter1 = core::pin::pin!(event.wait());
let mut waiter2 = core::pin::pin!(event.wait());
assert!(waiter1.as_mut().poll(&mut ctx).is_pending());
assert!(waiter2.as_mut().poll(&mut ctx).is_pending());
assert!(event.has_waiters());
event.set_one();
assert!(event.has_waiters());
assert!(waiter1.as_mut().poll(&mut ctx).is_ready());
assert!(event.has_waiters());
}
#[test]
pub fn event_has_waiter() {
let event = Event::new();
assert!(!event.has_waiters());
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiter = core::pin::pin!(event.wait());
assert!(waiter.as_mut().poll(&mut ctx).is_pending());
assert!(event.has_waiters());
event.set_one();
assert!(event.has_waiters());
assert!(waiter.as_mut().poll(&mut ctx).is_ready());
assert!(!event.has_waiters());
}
#[test]
pub fn test_event_standard() {
let event = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiter = event.wait();
assert!(core::pin::pin!(&mut waiter).poll(&mut ctx).is_pending());
event.set_one();
assert!(core::pin::pin!(&mut waiter).poll(&mut ctx).is_ready());
}
#[test]
pub fn test_countable_correctness_hotpath() {
let event = CountedEvent::new(Event::new());
assert_eq!(event.count(), 0);
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiting = core::pin::pin!(event.wait());
assert_eq!(event.count(), 0);
event.set_one();
assert!(waiting.as_mut().poll(&mut ctx).is_ready());
assert_eq!(event.count(), 0);
}
#[test]
pub fn test_drop_cancel_countable() {
let event = CountedEvent::new(Event::new());
assert_eq!(event.count(), 0);
setup_drop_cancel_test(&event);
assert_eq!(event.count(), 0);
}
#[test]
pub fn test_drop_cancel_try_wait() {
let event = Event::new();
assert!(!event.try_wait());
setup_drop_cancel_test(&event);
event.set_one();
assert!(event.try_wait());
}
#[test]
pub fn test_drop_cancel_real_wait() {
let event = Event::new();
assert!(!event.try_wait());
setup_drop_cancel_test(&event);
event.set_one();
assert!(can_poll_immediate(event.wait()));
}
#[test]
pub fn test_proper_order() {
use core::pin::pin;
let event = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut array: [_; 10] = core::array::from_fn(|_| {
let mut ev = event.wait();
assert!(pin!(&mut ev).poll(&mut ctx).is_pending());
ev
});
for i in 0..10 {
event.set_one();
assert!(pin!(&mut array[i]).poll(&mut ctx).is_ready());
}
}
#[test]
pub fn test_double_set() {
let event = Event::new();
let waker = Waker::from(Arc::new(TestWaker {}));
let mut ctx = Context::from_waker(&waker);
let mut waiter1 = core::pin::pin!(event.wait());
let mut waiter2 = core::pin::pin!(event.wait());
assert!(waiter1.as_mut().poll(&mut ctx).is_pending());
assert!(waiter2.as_mut().poll(&mut ctx).is_pending());
event.set_one();
event.set_one();
assert!(waiter1.as_mut().poll(&mut ctx).is_ready());
assert!(waiter2.as_mut().poll(&mut ctx).is_ready());
}
struct TestWaker {}
impl Wake for TestWaker {
fn wake(self: Arc<Self>) {}
}
#[test]
pub fn no_steal() {
let event = Event::new();
assert!(!event.try_wait());
let mut waiter = core::pin::pin!(event.wait());
let waker = Waker::from(Arc::new(TestWaker {}));
let mut context = Context::from_waker(&waker);
assert!(waiter.as_mut().poll(&mut context).is_pending());
event.set_one();
assert!(!event.try_wait());
assert!(waiter.as_mut().poll(&mut context).is_ready());
}
}