use std::{
future::Future,
panic::{self, AssertUnwindSafe},
pin::Pin,
ptr,
sync::{
Arc, Barrier, Mutex, PoisonError,
atomic::{AtomicBool, AtomicUsize, Ordering},
},
task::{Context, Poll, RawWaker, RawWakerVTable, Wake, Waker},
thread,
};
use futures::executor::block_on;
use ntest::timeout;
use crate::{Event, EventListener};
#[test]
fn a_listener_is_queued_before_it_is_first_polled() {
let event = Event::new();
let mut listener = event.listen();
assert_eq!(event.notify(1), 1);
assert!(ready(&mut listener));
}
#[test]
fn a_notification_is_not_kept_for_a_later_listener() {
let event = Event::new();
assert_eq!(event.notify(1), 0);
assert_eq!(event.notify_additional(1), 0);
let mut listener = event.listen();
assert!(!ready(&mut listener));
assert_eq!(event.notify(1), 1);
assert!(ready(&mut listener));
}
#[test]
fn listeners_are_notified_oldest_first() {
let event = Event::new();
let mut listeners = [event.listen(), event.listen(), event.listen()];
let counters = poll_all(&mut listeners);
for notified in 1..=listeners.len() {
assert_eq!(event.notify_additional(1), 1);
let wakes: Vec<_> = counters.iter().map(|counter| counter.wakes()).collect();
let expected: Vec<_> = (0..listeners.len())
.map(|i| usize::from(i < notified))
.collect();
assert_eq!(wakes, expected);
}
}
#[test]
fn notify_counts_the_listeners_notified_already() {
let event = Event::new();
let [mut first, mut second, mut third] = [event.listen(), event.listen(), event.listen()];
assert_eq!(event.notify(0), 0);
assert_eq!(event.notify(1), 1);
assert_eq!(event.notify(1), 0);
assert_eq!(event.notify(2), 1);
assert!(!ready(&mut third));
assert!(ready(&mut first));
assert_eq!(event.notify(2), 1);
assert!(ready(&mut second));
assert!(ready(&mut third));
}
#[test]
fn notify_all_notifies_every_listener_there_is() {
let event = Event::new();
let mut listeners: Vec<_> = (0..5).map(|_| event.listen()).collect();
assert_eq!(event.notify(1), 1);
assert_eq!(event.notify(usize::MAX), 4);
assert!(listeners.iter_mut().all(ready));
assert_eq!(event.notify(usize::MAX), 0);
}
#[test]
fn notify_additional_notifies_more_whatever_is_notified_already() {
let event = Event::new();
let [mut first, mut second, mut third] = [event.listen(), event.listen(), event.listen()];
assert_eq!(event.notify(1), 1);
assert_eq!(event.notify_additional(1), 1);
assert!(!ready(&mut third));
assert_eq!(event.notify(2), 0);
assert_eq!(event.notify_additional(5), 1);
assert!(ready(&mut first));
assert!(ready(&mut second));
assert!(ready(&mut third));
}
#[test]
fn a_notified_listener_completes_and_leaves_the_queue() {
let event = Event::new();
let [mut first, mut second] = [event.listen(), event.listen()];
assert_eq!(event.notify(1), 1);
assert!(ready(&mut first));
assert_eq!(format!("{event:?}"), "Event { listeners: 1, notified: 0 }");
assert_eq!(event.notify(1), 1);
assert!(ready(&mut second));
}
#[test]
fn a_notification_wakes_the_task_that_polled_the_listener() {
let event = Event::new();
let mut listener = event.listen();
let (counter, waker) = counting_waker();
assert!(poll(&mut listener, &waker).is_pending());
assert_eq!(counter.wakes(), 0);
event.notify(1);
assert_eq!(counter.wakes(), 1);
assert!(poll(&mut listener, &waker).is_ready());
assert_eq!(counter.wakes(), 1);
}
#[test]
fn a_listener_dropped_while_notified_passes_the_notification_on() {
let event = Event::new();
let [first, mut second] = [event.listen(), event.listen()];
let (counter, waker) = counting_waker();
assert!(poll(&mut second, &waker).is_pending());
assert_eq!(event.notify(1), 1);
drop(first);
assert_eq!(counter.wakes(), 1);
assert!(ready(&mut second));
}
#[test]
fn a_counting_notification_is_passed_on_only_where_nobody_else_is_notified() {
let event = Event::new();
let [first, mut second, mut third] = [event.listen(), event.listen(), event.listen()];
let (counter, waker) = counting_waker();
assert!(poll(&mut third, &waker).is_pending());
assert_eq!(event.notify(2), 2);
drop(first);
assert_eq!(counter.wakes(), 0);
assert!(!ready(&mut third));
assert!(ready(&mut second));
}
#[test]
fn an_additional_notification_is_passed_on_whatever_else_is_notified() {
let event = Event::new();
let [mut first, second, mut third] = [event.listen(), event.listen(), event.listen()];
let (counter, waker) = counting_waker();
assert!(poll(&mut third, &waker).is_pending());
assert_eq!(event.notify(1), 1);
assert_eq!(event.notify_additional(1), 1);
drop(second);
assert_eq!(counter.wakes(), 1);
assert!(ready(&mut first));
assert!(ready(&mut third));
}
#[test]
fn a_notification_passed_on_to_nobody_is_lost() {
let event = Event::new();
let first = event.listen();
assert_eq!(event.notify(1), 1);
drop(first);
let mut second = event.listen();
assert!(!ready(&mut second));
assert_eq!(event.notify(1), 1);
assert!(ready(&mut second));
}
#[test]
fn a_listener_dropped_before_being_notified_changes_nothing_else() {
let event = Event::new();
let [mut first, second, mut third] = [event.listen(), event.listen(), event.listen()];
let counters = poll_all([&mut first, &mut third]);
drop(second);
assert_eq!(counters.iter().map(|c| c.wakes()).sum::<usize>(), 0);
assert_eq!(event.notify(1), 1);
assert_eq!(counters[0].wakes(), 1);
assert_eq!(event.notify_additional(1), 1);
assert_eq!(counters[1].wakes(), 1);
assert_eq!(event.notify_additional(1), 0);
assert!(ready(&mut first));
assert!(ready(&mut third));
}
#[test]
fn dropping_the_oldest_listener_waiting_moves_notifications_on_to_the_next() {
let event = Event::new();
let [mut first, second, mut third] = [event.listen(), event.listen(), event.listen()];
assert_eq!(event.notify(1), 1);
drop(second);
assert_eq!(event.notify_additional(1), 1);
assert!(ready(&mut first));
assert!(ready(&mut third));
let mut fourth = event.listen();
assert_eq!(event.notify(1), 1);
assert!(ready(&mut fourth));
}
#[test]
fn a_listener_outlives_its_event() {
let event = Event::new();
let mut listener = event.listen();
drop(event);
assert!(!ready(&mut listener));
assert_eq!(format!("{listener:?}"), "EventListener { notified: false }");
}
#[test]
fn dropping_the_event_notifies_nobody() {
let event = Event::new();
let mut listeners = [event.listen(), event.listen()];
let counters = poll_all(&mut listeners);
assert_eq!(event.notify(1), 1);
drop(event);
assert_eq!(counters[0].wakes(), 1);
assert_eq!(counters[1].wakes(), 0);
let [first, second] = &mut listeners;
assert!(ready(first));
assert!(!ready(second));
assert_eq!(counters[1].wakes(), 0);
}
#[test]
fn a_listener_dropped_after_its_event_passes_its_notification_on() {
let event = Event::new();
let [first, mut second] = [event.listen(), event.listen()];
let (counter, waker) = counting_waker();
assert!(poll(&mut second, &waker).is_pending());
assert_eq!(event.notify(1), 1);
drop(event);
drop(first);
assert_eq!(counter.wakes(), 1);
assert!(ready(&mut second));
}
#[test]
fn a_listener_polled_after_completing_is_ready_again() {
let event = Event::new();
let mut listener = event.listen();
event.notify(1);
assert!(ready(&mut listener));
assert!(ready(&mut listener));
assert!(ready(&mut listener));
assert_eq!(format!("{listener:?}"), "EventListener { notified: true }");
assert_eq!(event.notify(usize::MAX), 0);
let mut later = event.listen();
assert_eq!(event.notify(1), 1);
assert!(ready(&mut later));
}
#[test]
fn only_the_waker_of_the_latest_poll_is_kept() {
let event = Event::new();
let mut listener = event.listen();
let (first, first_waker) = counting_waker();
let (second, second_waker) = counting_waker();
assert!(poll(&mut listener, &first_waker).is_pending());
assert_eq!(Arc::strong_count(&first), 3);
assert!(poll(&mut listener, &second_waker).is_pending());
assert_eq!(Arc::strong_count(&first), 2);
assert_eq!(Arc::strong_count(&second), 3);
event.notify(1);
assert_eq!(first.wakes(), 0);
assert_eq!(second.wakes(), 1);
}
#[test]
fn a_waker_is_cloned_only_to_be_stored_for_another_task() {
static FIRST: RawTask = RawTask::new(None);
static SECOND: RawTask = RawTask::new(None);
let event = Event::new();
let mut listener = event.listen();
let first = raw_waker(&FIRST);
let first_again = raw_waker(&FIRST);
let second = raw_waker(&SECOND);
assert!(!first.will_wake(&second));
assert!(poll(&mut listener, &first).is_pending());
assert_eq!(FIRST.counts(), [1, 0, 0]);
assert!(poll(&mut listener, &first).is_pending());
assert!(poll(&mut listener, &first_again).is_pending());
assert_eq!(FIRST.counts(), [1, 0, 0]);
assert!(poll(&mut listener, &second).is_pending());
assert_eq!(FIRST.counts(), [1, 1, 0]);
assert_eq!(SECOND.counts(), [1, 0, 0]);
assert_eq!(event.notify(1), 1);
assert_eq!(SECOND.counts(), [1, 0, 1]);
assert!(poll(&mut listener, &second).is_ready());
drop(listener);
assert_eq!(SECOND.counts(), [1, 0, 1]);
drop([first, first_again, second]);
assert_eq!(FIRST.counts(), [1, 3, 0]);
assert_eq!(SECOND.counts(), [1, 1, 1]);
}
#[test]
#[timeout(15000)]
fn a_notification_landing_while_a_first_poll_clones_its_waker_completes_it() {
static EVENT: Event = Event::new();
static NOTIFYING: RawTask = RawTask::new(Some(&EVENT));
let mut listener = EVENT.listen();
let waker = raw_waker(&NOTIFYING);
assert!(poll(&mut listener, &waker).is_ready());
assert_eq!(NOTIFYING.counts(), [1, 1, 0]);
assert_eq!(format!("{EVENT:?}"), "Event { listeners: 0, notified: 0 }");
assert!(poll(&mut listener, &waker).is_ready());
assert_eq!(NOTIFYING.counts(), [1, 1, 0]);
}
#[test]
#[timeout(15000)]
fn a_notification_landing_while_a_later_poll_clones_its_waker_completes_it() {
static EVENT: Event = Event::new();
static NOTIFYING: RawTask = RawTask::new(Some(&EVENT));
let mut listener = EVENT.listen();
let (counter, before) = counting_waker();
assert!(poll(&mut listener, &before).is_pending());
let waker = raw_waker(&NOTIFYING);
assert!(poll(&mut listener, &waker).is_ready());
assert_eq!(counter.wakes(), 1);
assert_eq!(NOTIFYING.counts(), [1, 1, 0]);
assert_eq!(format!("{EVENT:?}"), "Event { listeners: 0, notified: 0 }");
}
#[test]
#[timeout(15000)]
fn a_waker_may_come_back_into_the_event_from_its_wake() {
let event = Arc::new(Event::new());
let mut first = event.listen();
let second = event.listen();
let mut third = event.listen();
let comes_back = Arc::new(ComesBack {
event: event.clone(),
listener: Mutex::new(Some(second)),
woken: AtomicBool::new(false),
});
assert!(poll(&mut first, &Waker::from(comes_back.clone())).is_pending());
assert_eq!(event.notify(1), 1);
assert!(comes_back.woken.load(Ordering::SeqCst));
assert!(ready(&mut first));
assert!(ready(&mut third));
assert_eq!(format!("{event:?}"), "Event { listeners: 0, notified: 0 }");
}
#[test]
#[timeout(15000)]
fn a_waker_woken_by_a_passed_on_notification_may_come_back_into_the_event() {
let event = Arc::new(Event::new());
let first = event.listen();
let mut second = event.listen();
let mut third = event.listen();
let comes_back = Arc::new(ComesBack {
event: event.clone(),
listener: Mutex::new(None),
woken: AtomicBool::new(false),
});
assert!(poll(&mut second, &Waker::from(comes_back.clone())).is_pending());
assert_eq!(event.notify(1), 1);
drop(first);
assert!(comes_back.woken.load(Ordering::SeqCst));
assert!(ready(&mut second));
assert!(ready(&mut third));
}
#[test]
#[timeout(15000)]
fn a_waker_replaced_by_a_poll_is_dropped_clear_of_the_lock() {
let event = Event::new();
let mut listener = event.listen();
let (counter, holder) = holding(event.listen());
assert!(poll(&mut listener, &holder).is_pending());
drop(holder);
assert!(poll(&mut listener, Waker::noop()).is_pending());
assert_eq!(counter.wakes(), 0);
assert_eq!(format!("{event:?}"), "Event { listeners: 1, notified: 0 }");
}
#[test]
#[timeout(15000)]
fn a_waker_dropped_with_its_listener_is_dropped_clear_of_the_lock() {
let event = Event::new();
let notified = event.listen();
let mut listener = event.listen();
let mut last = event.listen();
let (counter, waker) = counting_waker();
assert!(poll(&mut last, &waker).is_pending());
let (holder_counter, holder) = holding(notified);
assert!(poll(&mut listener, &holder).is_pending());
drop(holder);
assert_eq!(event.notify(1), 1);
drop(listener);
assert_eq!(holder_counter.wakes(), 0);
assert_eq!(counter.wakes(), 1);
assert!(ready(&mut last));
}
#[test]
#[timeout(15000)]
fn a_waker_woken_by_a_notification_is_dropped_clear_of_the_lock() {
let event = Event::new();
let mut listener = event.listen();
let (counter, holder) = holding(event.listen());
assert!(poll(&mut listener, &holder).is_pending());
drop(holder);
assert_eq!(event.notify(1), 1);
assert_eq!(counter.wakes(), 1);
assert!(ready(&mut listener));
assert_eq!(format!("{event:?}"), "Event { listeners: 0, notified: 0 }");
}
#[test]
#[timeout(15000)]
fn a_waker_that_panics_does_not_keep_the_others_from_being_woken() {
for additional in [false, true] {
let event = Event::new();
let mut first = event.listen();
let mut second = event.listen();
let mut third = event.listen();
assert!(poll(&mut first, &Waker::from(Arc::new(PanicsOnWake))).is_pending());
let counters = poll_all([&mut second, &mut third]);
let notified = panic::catch_unwind(AssertUnwindSafe(|| {
if additional {
event.notify_additional(3)
} else {
event.notify(3)
}
}));
assert!(
notified.is_err(),
"the panic of the first waker reaches the caller"
);
for counter in &counters {
assert_eq!(counter.wakes(), 1, "additional: {additional}");
}
assert!(ready(&mut first));
assert!(ready(&mut second));
assert!(ready(&mut third));
}
}
#[test]
#[timeout(60000)]
fn a_panic_whose_payload_panics_as_it_drops_does_not_keep_the_others_from_being_woken() {
let event = Event::new();
let mut first = event.listen();
let mut second = event.listen();
let mut third = event.listen();
assert!(poll(&mut first, &Waker::from(Arc::new(PanicsOnWake))).is_pending());
let payload_waker = Waker::from(Arc::new(PanicsWithPayloadOnWake));
assert!(poll(&mut second, &payload_waker).is_pending());
let counters = poll_all([&mut third]);
let notified = panic::catch_unwind(AssertUnwindSafe(|| event.notify(3)));
assert!(
notified.is_err(),
"the panic of the first waker reaches the caller"
);
assert_eq!(counters[0].wakes(), 1);
assert!(ready(&mut third));
}
#[test]
fn an_event_and_its_listeners_cross_threads() {
fn sent_and_shared<T>()
where
T: Send + Sync,
{
}
fn sent_shared_and_kept<T>()
where
T: Future<Output = ()> + Send + Sync + Unpin + 'static,
{
}
sent_and_shared::<Event>();
sent_shared_and_kept::<EventListener>();
}
#[test]
fn an_event_allocates_nothing_until_first_used() {
static EVENT: Event = Event::new();
assert_eq!(EVENT.slots(), None);
drop(EVENT.listen());
assert_eq!(EVENT.slots(), Some(1));
let event = Event::default();
assert_eq!(format!("{event:?}"), "Event { listeners: 0, notified: 0 }");
assert_eq!(event.slots(), None);
event.notify(1);
assert_eq!(event.slots(), Some(0));
}
#[test]
fn a_listener_takes_the_slot_of_one_gone() {
let event = Event::new();
drop([event.listen(), event.listen(), event.listen()]);
assert_eq!(event.slots(), Some(3));
for _ in 0..10 {
let mut listeners = [event.listen(), event.listen(), event.listen()];
event.notify(2);
assert!(listeners.iter_mut().take(2).all(ready));
let _next = event.listen();
drop(listeners);
}
assert_eq!(event.slots(), Some(3));
}
#[test]
#[timeout(15000)]
fn a_notification_racing_listeners_reaches_them_or_their_checks_see_the_change() {
const LISTENING: usize = 2;
let rounds = if cfg!(miri) { 30 } else { 10_000 };
let event = Arc::new(Event::new());
let changed_in = Arc::new(AtomicUsize::new(0));
let start = Arc::new(Barrier::new(LISTENING + 1));
let listening: Vec<_> = (0..LISTENING)
.map(|_| {
let event = event.clone();
let changed_in = changed_in.clone();
let start = start.clone();
thread::spawn(move || {
for round in 1..=rounds {
start.wait();
let listener = event.listen();
if changed_in.load(Ordering::Relaxed) < round {
block_on(listener);
}
}
})
})
.collect();
for round in 1..=rounds {
start.wait();
changed_in.store(round, Ordering::Relaxed);
event.notify(usize::MAX);
}
for thread in listening {
thread.join().unwrap();
}
}
#[test]
#[timeout(15000)]
fn a_notification_finding_the_last_listener_dropped_comes_after_the_drop() {
let rounds = if cfg!(miri) { 30 } else { 1_000 };
for _ in 0..rounds {
let event = Arc::new(Event::new());
let listening = Arc::new(AtomicBool::new(false));
let before_drop = Arc::new(AtomicBool::new(false));
let dropper = thread::spawn({
let event = event.clone();
let listening = listening.clone();
let before_drop = before_drop.clone();
move || {
let listener = event.listen();
listening.store(true, Ordering::Release);
before_drop.store(true, Ordering::Relaxed);
drop(listener);
}
});
while !listening.load(Ordering::Acquire) {
thread::yield_now();
}
if event.notify(1) == 0 {
assert!(before_drop.load(Ordering::Relaxed));
}
dropper.join().unwrap();
}
}
#[test]
#[timeout(15000)]
fn one_notify_all_reaches_every_listener_on_many_threads() {
let (threads, rounds) = if cfg!(miri) { (3, 5) } else { (16, 100) };
let event = Arc::new(Event::new());
for _ in 0..rounds {
let barrier = Arc::new(Barrier::new(threads + 1));
let listeners: Vec<_> = (0..threads)
.map(|_| {
let event = event.clone();
let barrier = barrier.clone();
thread::spawn(move || {
let listener = event.listen();
barrier.wait();
block_on(listener);
})
})
.collect();
barrier.wait();
assert_eq!(event.notify(usize::MAX), threads);
for listener in listeners {
listener.join().unwrap();
}
}
}
#[test]
#[timeout(15000)]
fn a_notification_is_passed_down_listeners_dropped_once_notified() {
let rounds = if cfg!(miri) { 2 } else { 100 };
for _ in 0..rounds {
pass_down_listeners_dropped_once_notified(1, |event| event.notify(1));
}
}
#[test]
#[timeout(15000)]
fn additional_notifications_are_passed_down_listeners_dropped_once_notified() {
let rounds = if cfg!(miri) { 2 } else { 100 };
for _ in 0..rounds {
pass_down_listeners_dropped_once_notified(3, |event| event.notify_additional(3));
}
}
fn poll(listener: &mut EventListener, waker: &Waker) -> Poll<()> {
Pin::new(listener).poll(&mut Context::from_waker(waker))
}
fn ready(listener: &mut EventListener) -> bool {
poll(listener, Waker::noop()).is_ready()
}
fn poll_all<'a, I>(listeners: I) -> Vec<Arc<Counter>>
where
I: IntoIterator<Item = &'a mut EventListener>,
{
listeners
.into_iter()
.map(|listener| {
let (counter, waker) = counting_waker();
assert!(poll(listener, &waker).is_pending());
counter
})
.collect()
}
fn pass_down_listeners_dropped_once_notified<F>(takers: usize, notify: F)
where
F: FnOnce(&Event) -> usize,
{
let dropped = if cfg!(miri) { 3 } else { 6 };
let event = Event::new();
let registered = Arc::new(Barrier::new(dropped + 1));
let droppers: Vec<_> = (0..dropped)
.map(|_| {
let dropper = DropOnceWoken {
listener: Some(event.listen()),
registered: registered.clone(),
polled: false,
};
thread::spawn(move || block_on(dropper))
})
.collect();
let takers: Vec<_> = (0..takers)
.map(|_| {
let listener = event.listen();
thread::spawn(move || block_on(listener))
})
.collect();
registered.wait();
assert_eq!(notify(&event), takers.len());
for thread in droppers.into_iter().chain(takers) {
thread.join().unwrap();
}
assert_eq!(format!("{event:?}"), "Event { listeners: 0, notified: 0 }");
}
fn counting_waker() -> (Arc<Counter>, Waker) {
let counter = Arc::new(Counter::default());
let waker = Waker::from(counter.clone());
(counter, waker)
}
fn holding(listener: EventListener) -> (Arc<Counter>, Waker) {
let counter = Arc::new(Counter::default());
let waker = Waker::from(Arc::new(Holder {
listener: Some(listener),
counter: counter.clone(),
}));
(counter, waker)
}
#[derive(Default)]
struct Counter(AtomicUsize);
impl Counter {
fn wakes(&self) -> usize {
self.0.load(Ordering::SeqCst)
}
}
impl Wake for Counter {
fn wake(self: Arc<Self>) {
self.wake_by_ref();
}
fn wake_by_ref(self: &Arc<Self>) {
self.0.fetch_add(1, Ordering::SeqCst);
}
}
struct PanicsOnWake;
impl Wake for PanicsOnWake {
fn wake(self: Arc<Self>) {
panic!("a waker that panics as it is woken");
}
}
struct PanicsWithPayloadOnWake;
impl Wake for PanicsWithPayloadOnWake {
fn wake(self: Arc<Self>) {
panic::panic_any(PanicsOnDrop);
}
}
struct PanicsOnDrop;
impl Drop for PanicsOnDrop {
fn drop(&mut self) {
panic!("a panic payload that panics as it is dropped");
}
}
struct ComesBack {
event: Arc<Event>,
listener: Mutex<Option<EventListener>>,
woken: AtomicBool,
}
impl Wake for ComesBack {
fn wake(self: Arc<Self>) {
self.wake_by_ref();
}
fn wake_by_ref(self: &Arc<Self>) {
let held = self
.listener
.lock()
.unwrap_or_else(PoisonError::into_inner)
.take();
drop(held);
drop(self.event.listen());
self.event.notify_additional(1);
self.woken.store(true, Ordering::SeqCst);
}
}
struct Holder {
listener: Option<EventListener>,
counter: Arc<Counter>,
}
impl Wake for Holder {
fn wake(self: Arc<Self>) {
self.counter.wake_by_ref();
}
}
impl Drop for Holder {
fn drop(&mut self) {
drop(self.listener.take());
}
}
struct RawTask {
clones: AtomicUsize,
drops: AtomicUsize,
wakes: AtomicUsize,
notified_on_clone: Option<&'static Event>,
}
impl RawTask {
const fn new(notified_on_clone: Option<&'static Event>) -> Self {
Self {
clones: AtomicUsize::new(0),
drops: AtomicUsize::new(0),
wakes: AtomicUsize::new(0),
notified_on_clone,
}
}
fn counts(&self) -> [usize; 3] {
[&self.clones, &self.drops, &self.wakes].map(|count| count.load(Ordering::SeqCst))
}
}
fn raw_waker(task: &'static RawTask) -> Waker {
let data = ptr::from_ref(task).cast::<()>();
unsafe { Waker::from_raw(RawWaker::new(data, &RAW_TASK_VTABLE)) }
}
static RAW_TASK_VTABLE: RawWakerVTable =
RawWakerVTable::new(clone_raw_task, wake_raw_task, wake_raw_task, drop_raw_task);
unsafe fn clone_raw_task(data: *const ()) -> RawWaker {
let task = unsafe { &*data.cast::<RawTask>() };
task.clones.fetch_add(1, Ordering::SeqCst);
if let Some(event) = task.notified_on_clone {
event.notify(1);
}
RawWaker::new(data, &RAW_TASK_VTABLE)
}
unsafe fn wake_raw_task(data: *const ()) {
let task = unsafe { &*data.cast::<RawTask>() };
task.wakes.fetch_add(1, Ordering::SeqCst);
}
unsafe fn drop_raw_task(data: *const ()) {
let task = unsafe { &*data.cast::<RawTask>() };
task.drops.fetch_add(1, Ordering::SeqCst);
}
struct DropOnceWoken {
listener: Option<EventListener>,
registered: Arc<Barrier>,
polled: bool,
}
impl Future for DropOnceWoken {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let this = self.get_mut();
let Some(listener) = &mut this.listener else {
return Poll::Ready(());
};
if this.polled {
this.listener = None;
return Poll::Ready(());
}
this.polled = true;
assert!(Pin::new(listener).poll(cx).is_pending());
this.registered.wait();
Poll::Pending
}
}