1use fuchsia_sync::{Condvar, Mutex, MutexGuard};
22use std::future::poll_fn;
23use std::marker::PhantomPinned;
24use std::ops::{Deref, DerefMut};
25use std::pin::{Pin, pin};
26use std::ptr::NonNull;
27use std::sync::Arc;
28use std::task::{Poll, Wake, Waker};
29
30#[derive(Default)]
35pub struct Condition<T>(Arc<Mutex<Inner<T>>>);
36
37impl<T> Condition<T> {
38 pub fn new(data: T) -> Self {
40 Self(Arc::new(Mutex::new(Inner { head: None, count: 0, data })))
41 }
42
43 pub fn waker_count(&self) -> usize {
45 self.0.lock().count
46 }
47
48 pub fn lock(&self) -> ConditionGuard<'_, T> {
50 ConditionGuard(self.0.lock())
51 }
52
53 pub async fn when<R>(
55 &self,
56 mut poll: impl for<'b> FnMut(&mut ConditionGuard<'b, T>) -> Poll<R>,
57 ) -> R {
58 let mut entry = pin!(self.waker_entry());
59 poll_fn(move |cx| {
60 let guard = self.0.lock();
61 let mut cond_guard = ConditionGuard(guard);
62 let result = poll(&mut cond_guard);
63 if result.is_pending() {
64 cond_guard.add_waker(entry.as_mut(), cx.waker().clone());
65 }
66 result
67 })
68 .await
69 }
70
71 pub fn waker_entry(&self) -> WakerEntry<T> {
73 WakerEntry {
74 list: Some(self.0.clone()),
75 node: Node { next: None, prev: None, waker: None, _pinned: PhantomPinned },
76 }
77 }
78}
79
80#[derive(Default)]
81struct Inner<T> {
82 head: Option<NonNull<Node>>,
83 count: usize,
84 data: T,
85}
86
87unsafe impl<T: Send> Send for Inner<T> {}
89
90pub struct ConditionGuard<'a, T>(MutexGuard<'a, Inner<T>>);
92
93impl<'a, T> ConditionGuard<'a, T> {
94 pub fn add_waker(&mut self, waker_entry: Pin<&mut WakerEntry<T>>, waker: Waker) {
100 if let Some(list) = &waker_entry.list {
102 assert!(list.data_ptr() == &mut *self.0, "Cannot add waker to different Condition");
103 }
104 let waker_entry = unsafe { waker_entry.get_unchecked_mut() };
106 unsafe {
108 waker_entry.node.add(&mut *self.0, waker);
109 }
110 }
111
112 pub fn drain_wakers<'b>(&'b mut self) -> Drainer<'b, 'a, T> {
117 Drainer(self)
118 }
119
120 pub fn waker_count(&self) -> usize {
122 self.0.count
123 }
124
125 pub fn block_until(&mut self, mut condition: impl FnMut(&mut Self) -> bool) {
129 struct Condv(Condvar);
130
131 impl Wake for Condv {
132 fn wake(self: Arc<Self>) {
133 self.0.notify_one();
134 }
135 }
136
137 let condv = Arc::new(Condv(Condvar::new()));
138 let mut entry = pin!(WakerEntry {
139 list: None,
140 node: Node { next: None, prev: None, waker: None, _pinned: PhantomPinned },
141 });
142
143 while !condition(self) {
144 self.add_waker(entry.as_mut(), Waker::from(condv.clone()));
145 condv.0.wait(&mut self.0);
146 }
147
148 unsafe {
150 entry.get_unchecked_mut().node.remove(&mut *self.0);
151 }
152 }
153}
154
155impl<T> Deref for ConditionGuard<'_, T> {
156 type Target = T;
157
158 fn deref(&self) -> &Self::Target {
159 &self.0.data
160 }
161}
162
163impl<T> DerefMut for ConditionGuard<'_, T> {
164 fn deref_mut(&mut self) -> &mut Self::Target {
165 &mut self.0.data
166 }
167}
168
169pub struct WakerEntry<T> {
171 list: Option<Arc<Mutex<Inner<T>>>>,
172 node: Node,
173}
174
175impl<T> Drop for WakerEntry<T> {
176 fn drop(&mut self) {
177 if let Some(list) = &self.list {
178 self.node.remove(&mut *list.lock());
179 }
180 }
181}
182
183struct Node {
185 next: Option<NonNull<Node>>,
186 prev: Option<NonNull<Node>>,
187 waker: Option<Waker>,
188 _pinned: PhantomPinned,
189}
190
191unsafe impl Send for Node {}
193
194impl Node {
195 unsafe fn add<T>(&mut self, inner: &mut Inner<T>, waker: Waker) {
199 if self.waker.is_none() {
200 self.prev = None;
201 self.next = inner.head;
202 inner.head = Some(self.into());
203 if let Some(mut next) = self.next {
204 unsafe {
207 next.as_mut().prev = Some(self.into());
208 }
209 }
210 inner.count += 1;
211 }
212 self.waker = Some(waker);
213 }
214
215 fn remove<T>(&mut self, inner: &mut Inner<T>) -> Option<Waker> {
216 if self.waker.is_none() {
217 debug_assert!(self.prev.is_none() && self.next.is_none());
218 return None;
219 }
220 if let Some(mut next) = self.next {
221 unsafe { next.as_mut().prev = self.prev };
223 }
224 if let Some(mut prev) = self.prev {
225 unsafe { prev.as_mut().next = self.next };
227 } else {
228 debug_assert_eq!(inner.head, Some(self.into()));
229 inner.head = self.next;
230 }
231 self.prev = None;
232 self.next = None;
233 inner.count -= 1;
234 self.waker.take()
235 }
236}
237
238pub struct Drainer<'a, 'b, T>(&'a mut ConditionGuard<'b, T>);
240
241impl<T> Iterator for Drainer<'_, '_, T> {
242 type Item = Waker;
243 fn next(&mut self) -> Option<Self::Item> {
244 if let Some(mut head) = self.0.0.head {
245 unsafe { head.as_mut().remove(&mut self.0.0) }
247 } else {
248 None
249 }
250 }
251
252 fn size_hint(&self) -> (usize, Option<usize>) {
253 (self.0.0.count, Some(self.0.0.count))
254 }
255}
256
257impl<T> ExactSizeIterator for Drainer<'_, '_, T> {
258 fn len(&self) -> usize {
259 self.0.0.count
260 }
261}
262
263#[cfg(all(target_os = "fuchsia", test))]
264mod tests {
265 use super::Condition;
266 use crate::TestExecutor;
267 use futures::StreamExt;
268 use futures::stream::FuturesUnordered;
269 use std::pin::pin;
270 use std::sync::atomic::{AtomicU64, Ordering};
271 use std::task::{Poll, Waker};
272
273 #[test]
274 fn test_condition_can_waker_multiple_wakers() {
275 let mut executor = TestExecutor::new();
276 let condition = Condition::new(());
277
278 static COUNT: u64 = 10;
279
280 let counter = AtomicU64::new(0);
281
282 let mut futures = FuturesUnordered::new();
284
285 for _ in 0..COUNT {
286 futures.push(condition.when(|_| {
287 if counter.fetch_add(1, Ordering::Relaxed) >= COUNT {
288 Poll::Ready(())
289 } else {
290 Poll::Pending
291 }
292 }));
293 }
294
295 assert!(executor.run_until_stalled(&mut futures.next()).is_pending());
296
297 assert_eq!(counter.load(Ordering::Relaxed), COUNT);
298 assert_eq!(condition.waker_count(), COUNT as usize);
299
300 {
301 let mut guard = condition.lock();
302 let drainer = guard.drain_wakers();
303 assert_eq!(drainer.len(), COUNT as usize);
304 for waker in drainer {
305 waker.wake();
306 }
307 }
308
309 assert!(executor.run_until_stalled(&mut futures.collect::<Vec<_>>()).is_ready());
310 assert_eq!(counter.load(Ordering::Relaxed), COUNT * 2);
311 }
312
313 #[test]
314 fn test_dropping_waker_entry_removes_from_list() {
315 let condition = Condition::new(());
316
317 let entry1 = pin!(condition.waker_entry());
318 condition.lock().add_waker(entry1, Waker::noop().clone());
319
320 {
321 let entry2 = pin!(condition.waker_entry());
322 condition.lock().add_waker(entry2, Waker::noop().clone());
323
324 assert_eq!(condition.waker_count(), 2);
325 }
326
327 assert_eq!(condition.waker_count(), 1);
328 {
329 let mut guard = condition.lock();
330 assert_eq!(guard.drain_wakers().count(), 1);
331 }
332
333 assert_eq!(condition.waker_count(), 0);
334
335 let entry3 = pin!(condition.waker_entry());
336 condition.lock().add_waker(entry3, Waker::noop().clone());
337
338 assert_eq!(condition.waker_count(), 1);
339 }
340
341 #[test]
342 fn test_waker_can_be_added_multiple_times() {
343 let condition = Condition::new(());
344
345 let mut entry1 = pin!(condition.waker_entry());
346 condition.lock().add_waker(entry1.as_mut(), Waker::noop().clone());
347
348 let mut entry2 = pin!(condition.waker_entry());
349 condition.lock().add_waker(entry2.as_mut(), Waker::noop().clone());
350
351 assert_eq!(condition.waker_count(), 2);
352 {
353 let mut guard = condition.lock();
354 assert_eq!(guard.drain_wakers().count(), 2);
355 }
356 assert_eq!(condition.waker_count(), 0);
357
358 condition.lock().add_waker(entry1, Waker::noop().clone());
359 condition.lock().add_waker(entry2, Waker::noop().clone());
360
361 assert_eq!(condition.waker_count(), 2);
362
363 {
364 let mut guard = condition.lock();
365 assert_eq!(guard.drain_wakers().count(), 2);
366 }
367 assert_eq!(condition.waker_count(), 0);
368 }
369
370 #[test]
371 #[should_panic]
372 fn test_adding_waker_to_different_condition() {
373 let condition1 = Condition::new(());
374 let condition2 = Condition::new(());
375
376 let entry2 = pin!(condition2.waker_entry());
377
378 let mut guard = condition1.lock();
379 guard.add_waker(entry2, std::task::Waker::noop().clone());
381 }
382
383 #[test]
384 fn test_block_until_immediate() {
385 let condition = Condition::new(42);
386 let mut guard = condition.lock();
387 guard.block_until(|val| **val == 42);
388 assert_eq!(*guard, 42);
389 }
390
391 #[test]
392 fn test_block_until_blocking() {
393 use std::sync::Arc;
394 use std::thread;
395 use std::time::Duration;
396
397 let condition = Arc::new(Condition::new(0));
398 let condition_clone = condition.clone();
399
400 let handle = thread::spawn(move || {
401 thread::sleep(Duration::from_millis(50));
403 let mut guard = condition_clone.lock();
404 *guard = 1;
405 for waker in guard.drain_wakers() {
406 waker.wake();
407 }
408 });
409
410 let mut guard = condition.lock();
411 guard.block_until(|val| **val == 1);
412 assert_eq!(*guard, 1);
413
414 handle.join().unwrap();
415 }
416}