Skip to main content

conc_util/event/
onceevent.rs

1use core::{
2    mem::ManuallyDrop,
3    pin::Pin,
4    task::{self, Waker},
5};
6
7use alloc::vec::Vec;
8
9use crate::{event::Event, sync::{OnceFlag, SpinLock}};
10
11#[derive(Debug)]
12pub struct OnceEvent {
13    used: OnceFlag,
14    wakers: SpinLock<ManuallyDrop<Vec<Waker>>>,
15}
16
17impl OnceEvent {
18    pub fn new() -> Self {
19        Self {
20            used: OnceFlag::new(),
21            wakers: SpinLock::new(ManuallyDrop::new(Vec::new())),
22        }
23    }
24}
25
26impl Future for &OnceEvent {
27    type Output = ();
28
29    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
30        if self.used.fired() {
31            return task::Poll::Ready(());
32        }
33
34        let mut wakers = self.wakers.lock();
35
36        if self.used.fired() {
37            return task::Poll::Ready(());
38        }
39
40        wakers.push(cx.waker().clone());
41        return task::Poll::Pending;
42    }
43}
44
45impl Event for OnceEvent {
46    type Wait<'a> = &'a Self;
47    
48    fn fire(&self) {
49        if self.used.fire() {
50            return;
51        }
52
53        let mut lock = self.wakers.lock();
54        // SAFETY:
55        // 1) Value is taken once - `used` is checked at the beginning
56        // 2) Value is never used again - `poll` checks the same `used`
57        let wakers = unsafe { ManuallyDrop::take(&mut lock) };
58        drop(lock);
59
60        for waker in wakers {
61            waker.wake();
62        }
63    }
64    
65    fn wait<'a>(&'a self) -> Self::Wait<'a> {
66        self
67    }
68}
69
70impl Drop for OnceEvent {
71    fn drop(&mut self) {
72        if !self.used.fired_mut() {
73            // SAFETY: this is only dropped here and taken in `fire()`,
74            // but it also sets the `used` flag which is checked above.
75            unsafe { ManuallyDrop::drop(self.wakers.get()) };
76        }
77    }
78}