1#![allow(unsafe_code)]
4
5use core::fmt;
6use core::future::Future;
7use core::pin::Pin;
8use core::task::{Context, Poll};
9
10use super::internal::{Ordering, UnsafeCell};
11use super::list::List;
12use super::queue::{Arrivals, FIRST_BIT, Policy, QUEUED, Step, WaitQueue};
13use super::waiter::{Cancel, Wait, WakeList};
14
15const SET: usize = 1 << FIRST_BIT;
16
17pub struct Event {
32 queue: WaitQueue,
33 waiting: UnsafeCell<List>,
34}
35
36unsafe impl Send for Event {}
38unsafe impl Sync for Event {}
40
41impl Event {
42 loom_const_fn! {
43 pub fn new() -> Self {
45 Self::with_state(0)
46 }
47 }
48
49 loom_const_fn! {
50 pub(super) fn new_set(set: bool) -> Self {
52 Self::with_state(if set { SET } else { 0 })
53 }
54 }
55
56 loom_const_fn! {
57 fn with_state(state: usize) -> Self {
58 Self { queue: WaitQueue::new(state), waiting: UnsafeCell::new(List::new()) }
59 }
60 }
61
62 pub fn set(&self) {
65 self.transition(|state| {
66 if state & SET != 0 {
67 Step::Keep
68 } else if state & QUEUED != 0 {
69 Step::Drain(state | SET)
70 } else {
71 Step::Set(state | SET)
72 }
73 });
74 }
75
76 pub fn is_set(&self) -> bool {
78 self.queue.state.load(Ordering::Acquire) & SET != 0
79 }
80
81 pub fn wait(&self) -> EventWait<'_> {
83 EventWait {
84 event: self,
85 wait: Wait::new(),
86 }
87 }
88}
89
90impl Policy for Event {
91 fn queue(&self) -> &WaitQueue {
92 &self.queue
93 }
94
95 fn pass(&self, arrivals: Arrivals, woken: &mut WakeList<'_>, _wake_front: bool) -> usize {
96 let pool = &self.queue;
97 let set = self.is_set();
98 self.waiting.with_mut(|waiting| unsafe {
100 let waiting = &mut *waiting;
101 waiting.absorb(arrivals, pool);
102 waiting.tidy(&self.queue);
103 while set && let Some(node) = waiting.front(pool) {
104 waiting.pop_front();
105 woken.grant(node);
106 }
107 if waiting.front(pool).is_none() {
108 QUEUED
109 } else {
110 0
111 }
112 })
113 }
114}
115
116impl Drop for Event {
117 fn drop(&mut self) {
118 let pool = &self.queue;
119 self.waiting
121 .with_mut(|waiting| unsafe { (*waiting).clear(pool) });
122 }
123}
124
125impl Default for Event {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl fmt::Debug for Event {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 f.debug_struct("Event")
134 .field("set", &self.is_set())
135 .finish()
136 }
137}
138
139#[must_use = "futures do nothing unless polled"]
141pub struct EventWait<'a> {
142 event: &'a Event,
143 wait: Wait,
144}
145
146impl Future for EventWait<'_> {
147 type Output = ();
148
149 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
150 let this = self.get_mut();
151 let event = this.event;
152 if this.wait.is_queued() {
153 return this.wait.poll(&event.queue, Some(cx.waker())).map(drop);
154 }
155 if event.is_set() {
156 return Poll::Ready(());
157 }
158 event.enqueue(&mut this.wait, 0, cx.waker());
159 this.wait.poll(&event.queue, None).map(drop)
160 }
161}
162
163impl Drop for EventWait<'_> {
164 fn drop(&mut self) {
165 if let Cancel::Withdrawn(_) = self.wait.cancel(&self.event.queue) {
166 self.event.withdrawn(false);
167 }
168 }
169}
170
171impl fmt::Debug for EventWait<'_> {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.debug_struct("EventWait").finish_non_exhaustive()
174 }
175}
176
177#[cfg(all(test, not(loom)))]
178mod tests {
179 use super::*;
180 use crate::sync::test_support::{Polled, block_on};
181 use std::sync::Arc;
182
183 #[test]
184 fn setting_wakes_every_waiter_and_later_waits_pass() {
185 let event = Event::new();
186 let mut waiters: Vec<_> = (0..3).map(|_| Polled::new(event.wait())).collect();
187 for waiter in &mut waiters {
188 waiter.pending();
189 }
190 drop(waiters.pop());
191 event.set();
192 event.set();
193 for waiter in &mut waiters {
194 assert_eq!(waiter.wakes(), 1);
195 waiter.ready();
196 }
197 Polled::new(event.wait()).ready();
198 }
199
200 #[test]
201 fn a_set_from_another_thread_is_seen() {
202 let event = Arc::new(Event::new());
203 let setter = Arc::clone(&event);
204 let thread = std::thread::spawn(move || setter.set());
205 block_on(event.wait());
206 thread.join().expect("setter");
207 assert!(event.is_set());
208 }
209}