conc_util/event/
onceevent.rs1#![cfg(feature = "alloc")]
2
3use core::{
4 mem::ManuallyDrop,
5 pin::Pin,
6 task::{self, Waker},
7};
8
9use alloc::vec::Vec;
10
11use crate::{event::Event, sync::{OnceFlag, SpinLock}};
12
13#[derive(Debug)]
14pub struct OnceEvent {
15 used: OnceFlag,
16 wakers: SpinLock<ManuallyDrop<Vec<Waker>>>,
17}
18
19impl OnceEvent {
20 pub fn new() -> Self {
21 Self {
22 used: OnceFlag::new(),
23 wakers: SpinLock::new(ManuallyDrop::new(Vec::new())),
24 }
25 }
26}
27
28impl Event for OnceEvent {
29 fn fire(&self) {
30 if self.used.fire() {
31 return;
32 }
33
34 let mut lock = self.wakers.lock();
35 let wakers = unsafe { ManuallyDrop::take(&mut lock) };
39 drop(lock);
40
41 for waker in wakers {
42 waker.wake();
43 }
44 }
45}
46
47impl Drop for OnceEvent {
48 fn drop(&mut self) {
49 if !self.used.fired_mut() {
50 unsafe { ManuallyDrop::drop(self.wakers.get()) };
53 }
54 }
55}
56
57impl Future for &OnceEvent {
58 type Output = ();
59
60 fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
61 if self.used.fired() {
62 return task::Poll::Ready(());
63 }
64
65 let mut wakers = self.wakers.lock();
66
67 if self.used.fired() {
68 return task::Poll::Ready(());
69 }
70
71 wakers.push(cx.waker().clone());
72 return task::Poll::Pending;
73 }
74}