1extern crate alloc;
9use alloc::{boxed::Box, sync};
10
11use crate::{
12 alloc::SyncVec,
13 sync_types::{self, Lock as _},
14};
15use core::{cell, convert, future, marker, ops, pin, sync::atomic, task};
16
17pub struct TestNopLock<T: marker::Send> {
21 locked: atomic::AtomicBool,
22 v: cell::UnsafeCell<T>,
23}
24
25impl<T: marker::Send> convert::From<T> for TestNopLock<T> {
26 fn from(value: T) -> Self {
27 Self {
28 locked: atomic::AtomicBool::new(false),
29 v: cell::UnsafeCell::new(value),
30 }
31 }
32}
33
34unsafe impl<T: marker::Send> marker::Send for TestNopLock<T> {}
35unsafe impl<T: marker::Send> marker::Sync for TestNopLock<T> {}
36
37impl<T: marker::Send> sync_types::Lock<T> for TestNopLock<T> {
38 type Guard<'a>
39 = TestNopLockGuard<'a, T>
40 where
41 Self: 'a;
42
43 fn lock(&self) -> Self::Guard<'_> {
44 assert_eq!(
45 self.locked
46 .compare_exchange(false, true, atomic::Ordering::Acquire, atomic::Ordering::Relaxed),
47 Ok(false),
48 "Testing TestNopLocks are not expected to ever be contended."
49 );
50 TestNopLockGuard { lock: self }
51 }
52}
53
54impl<T: marker::Send> sync_types::ConstructibleLock<T> for TestNopLock<T> {
55 fn get_mut(&mut self) -> &mut T {
56 assert!(!self.locked.load(atomic::Ordering::Relaxed));
57 let p = self.v.get();
58 unsafe { &mut *p }
59 }
60}
61
62pub struct TestNopLockGuard<'a, T: marker::Send> {
65 lock: &'a TestNopLock<T>,
66}
67
68impl<'a, T: marker::Send> Drop for TestNopLockGuard<'a, T> {
69 fn drop(&mut self) {
70 assert_eq!(
71 self.lock
72 .locked
73 .compare_exchange(true, false, atomic::Ordering::Acquire, atomic::Ordering::Relaxed),
74 Ok(true),
75 "Testing TestNopLock with active lock guard found unlocked."
76 );
77 }
78}
79
80impl<'a, T: marker::Send> ops::Deref for TestNopLockGuard<'a, T> {
81 type Target = T;
82
83 fn deref(&self) -> &Self::Target {
84 let p = self.lock.v.get();
85 unsafe { &*p }
87 }
88}
89
90impl<'a, T: marker::Send> ops::DerefMut for TestNopLockGuard<'a, T> {
91 fn deref_mut(&mut self) -> &mut Self::Target {
92 let p = self.lock.v.get();
93 unsafe { &mut *p }
95 }
96}
97
98pub struct TestNopRwLock<T: marker::Send + marker::Sync> {
103 locked: atomic::AtomicIsize,
104 v: cell::UnsafeCell<T>,
105}
106
107impl<T: marker::Send + marker::Sync> convert::From<T> for TestNopRwLock<T> {
108 fn from(value: T) -> Self {
109 Self {
110 locked: atomic::AtomicIsize::new(0),
111 v: cell::UnsafeCell::new(value),
112 }
113 }
114}
115
116unsafe impl<T: marker::Send + marker::Sync> marker::Send for TestNopRwLock<T> {}
117unsafe impl<T: marker::Send + marker::Sync> marker::Sync for TestNopRwLock<T> {}
118
119impl<T: marker::Send + marker::Sync> sync_types::RwLock<T> for TestNopRwLock<T> {
120 type ReadGuard<'a>
121 = TestNopRwLockReadGuard<'a, T>
122 where
123 Self: 'a;
124 type WriteGuard<'a>
125 = TestNopRwLockWriteGuard<'a, T>
126 where
127 Self: 'a;
128
129 fn read(&self) -> Self::ReadGuard<'_> {
130 assert!(
131 self.locked.fetch_add(1, atomic::Ordering::Acquire) >= 0,
132 "Testing TestNopRwLocks are not expected to ever be contended."
133 );
134 TestNopRwLockReadGuard { lock: self }
135 }
136
137 fn write(&self) -> Self::WriteGuard<'_> {
138 assert_eq!(
139 self.locked.fetch_sub(1, atomic::Ordering::Acquire),
140 0,
141 "Testing TestNopRwLocks are not expected to ever be contended."
142 );
143 TestNopRwLockWriteGuard { lock: self }
144 }
145
146 fn get_mut(&mut self) -> &mut T {
147 assert_eq!(self.locked.load(atomic::Ordering::Relaxed), 0);
148 let p = self.v.get();
149 unsafe { &mut *p }
150 }
151}
152
153pub struct TestNopRwLockReadGuard<'a, T: marker::Send + marker::Sync> {
156 lock: &'a TestNopRwLock<T>,
157}
158
159impl<'a, T: marker::Send + marker::Sync> Drop for TestNopRwLockReadGuard<'a, T> {
160 fn drop(&mut self) {
161 assert!(
162 self.lock.locked.fetch_sub(1, atomic::Ordering::Release) > 0,
163 "Testing TestNopRwLock with active read guard found unlocked or write locked."
164 );
165 }
166}
167
168impl<'a, T: marker::Send + marker::Sync> ops::Deref for TestNopRwLockReadGuard<'a, T> {
169 type Target = T;
170
171 fn deref(&self) -> &Self::Target {
172 let p = self.lock.v.get();
173 unsafe { &*p }
176 }
177}
178
179pub struct TestNopRwLockWriteGuard<'a, T: marker::Send + marker::Sync> {
182 lock: &'a TestNopRwLock<T>,
183}
184
185impl<'a, T: marker::Send + marker::Sync> Drop for TestNopRwLockWriteGuard<'a, T> {
186 fn drop(&mut self) {
187 assert_eq!(
188 self.lock.locked.fetch_add(1, atomic::Ordering::Release),
189 -1,
190 "Testing TestNopRwLock with active lock write guard found unlocked or read locked."
191 );
192 }
193}
194
195impl<'a, T: marker::Send + marker::Sync> ops::Deref for TestNopRwLockWriteGuard<'a, T> {
196 type Target = T;
197
198 fn deref(&self) -> &Self::Target {
199 let p = self.lock.v.get();
200 unsafe { &*p }
203 }
204}
205
206impl<'a, T: marker::Send + marker::Sync> ops::DerefMut for TestNopRwLockWriteGuard<'a, T> {
207 fn deref_mut(&mut self) -> &mut Self::Target {
208 let p = self.lock.v.get();
209 unsafe { &mut *p }
212 }
213}
214
215pub struct TestNopSyncTypes;
217
218impl sync_types::SyncTypes for TestNopSyncTypes {
219 type Lock<T: marker::Send> = TestNopLock<T>;
220 type RwLock<T: marker::Send + marker::Sync> = TestNopRwLock<T>;
221 type SyncRcPtrFactory = sync_types::GenericArcFactory;
222}
223
224trait QueuedTaskDispatch: marker::Send {
230 fn poll_pinned(&mut self, cx: &mut task::Context<'_>) -> bool;
236}
237
238struct QueuedTask<F: future::Future + Send>
245where
246 F::Output: Send + 'static,
247{
248 f: F,
250 result: sync_types::GenericArc<TestNopLock<Option<F::Output>>>,
256}
257
258impl<F: future::Future + Send> QueuedTaskDispatch for QueuedTask<F>
259where
260 F::Output: Send + 'static,
261{
262 fn poll_pinned(&mut self, cx: &mut task::Context<'_>) -> bool {
263 let f = unsafe { pin::Pin::new_unchecked(&mut self.f) };
266 match future::Future::poll(f, cx) {
267 task::Poll::Ready(result) => {
268 *self.result.lock() = Some(result);
269 true
270 }
271 task::Poll::Pending => false,
272 }
273 }
274}
275
276enum TaskStatus {
278 Blocked,
283 Runnable,
286}
287
288struct TaskQueueEntry {
291 id: u64,
294 status: TaskStatus,
296 task: Option<pin::Pin<Box<dyn QueuedTaskDispatch>>>,
298 waiter_waker: Option<task::Waker>,
302}
303
304struct Waker {
306 task_id: u64,
307 executor: sync_types::GenericArc<TestAsyncExecutor>,
308}
309
310impl alloc::task::Wake for Waker {
311 fn wake(self: sync::Arc<Self>) {
312 let executor = &self.executor;
313 let mut tasks = executor.tasks.lock();
314 for t in tasks.iter_mut() {
315 if t.id == self.task_id && matches!(t.status, TaskStatus::Blocked) {
316 t.status = TaskStatus::Runnable
317 }
318 }
319 }
320}
321
322enum TaskWaiterState<T: marker::Send> {
323 Pending {
324 executor: sync_types::GenericArc<TestAsyncExecutor>,
326 task_id: u64,
329 result: sync_types::GenericArc<TestNopLock<Option<T>>>,
332 },
333 Done,
334}
335
336pub struct TestAsyncExecutorTaskWaiter<T: marker::Send> {
347 state: TaskWaiterState<T>,
348}
349
350impl<T: marker::Send> TestAsyncExecutorTaskWaiter<T> {
351 pub fn take(mut self) -> Option<T> {
358 match &mut self.state {
359 TaskWaiterState::Pending {
360 executor: _,
361 task_id: _,
362 result,
363 } => {
364 let result = result.lock().take();
365 self.state = TaskWaiterState::Done;
366 result
367 }
368 TaskWaiterState::Done => None,
369 }
370 }
371}
372
373impl<T: marker::Send> Drop for TestAsyncExecutorTaskWaiter<T> {
374 fn drop(&mut self) {
375 match &self.state {
376 TaskWaiterState::Pending {
377 executor,
378 task_id,
379 result,
380 } => {
381 if !result.lock().is_some() {
382 executor.remove_task(*task_id);
383 }
384 }
385 TaskWaiterState::Done => (),
386 }
387 }
388}
389
390impl<T: marker::Send> Unpin for TestAsyncExecutorTaskWaiter<T> {}
391
392impl<T: marker::Send> future::Future for TestAsyncExecutorTaskWaiter<T> {
393 type Output = T;
394
395 fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
396 let this = self.get_mut();
397 match &this.state {
398 TaskWaiterState::Pending {
399 executor,
400 task_id,
401 result,
402 } => {
403 let mut locked_result = result.lock();
404 if let Some(result) = locked_result.take() {
405 drop(locked_result);
406 this.state = TaskWaiterState::Done;
407 task::Poll::Ready(result)
408 } else {
409 let mut tasks = executor.tasks.lock();
410 let task = tasks.iter_mut().find(|task| task.id == *task_id).unwrap();
411 task.waiter_waker = Some(cx.waker().clone());
412 task::Poll::Pending
413 }
414 }
415 TaskWaiterState::Done => unreachable!(),
416 }
417 }
418}
419
420pub struct TestAsyncExecutor {
430 tasks: TestNopLock<SyncVec<TaskQueueEntry>>,
432 next_id: atomic::AtomicU64,
435}
436
437impl TestAsyncExecutor {
438 pub fn new() -> sync_types::GenericArc<Self> {
440 <sync_types::GenericArcFactory as sync_types::SyncRcPtrFactory>::try_new(Self {
441 tasks: TestNopLock::from(SyncVec::new()),
442 next_id: atomic::AtomicU64::new(0),
443 })
444 .unwrap()
445 }
446
447 pub fn spawn<F: future::Future + Send + 'static>(
454 this: &sync_types::GenericArc<Self>,
455 f: F,
456 ) -> TestAsyncExecutorTaskWaiter<F::Output>
457 where
458 F::Output: Send + 'static,
459 {
460 let id = this.next_id.fetch_add(1, atomic::Ordering::Relaxed);
461
462 let result =
463 <sync_types::GenericArcFactory as sync_types::SyncRcPtrFactory>::try_new(TestNopLock::from(None)).unwrap();
464 let waiter = TestAsyncExecutorTaskWaiter {
465 state: TaskWaiterState::Pending {
466 executor: this.clone(),
467 task_id: id,
468 result: result.clone(),
469 },
470 };
471
472 let task = Box::pin(QueuedTask { f, result }) as pin::Pin<Box<dyn QueuedTaskDispatch>>;
473 let tasks = this.tasks.lock();
474 let (mut tasks, r) = SyncVec::try_reserve_exact(&this.tasks, tasks, 1);
475 r.unwrap();
476 tasks.push(TaskQueueEntry {
477 id,
478 status: TaskStatus::Runnable,
479 task: Some(task),
480 waiter_waker: None,
481 });
482
483 waiter
484 }
485
486 fn remove_task(&self, id: u64) {
487 let mut tasks = self.tasks.lock();
488 if let Some(index) = tasks.iter().position(|task| task.id == id) {
489 let entry = tasks.remove(index);
493 drop(tasks);
494 drop(entry);
495 };
496 }
497
498 pub fn run_to_completion(this: &sync_types::GenericArc<Self>) {
515 let mut last_polled: Option<(usize, u64)> = None;
516 loop {
517 let mut tasks = this.tasks.lock();
518 if tasks.is_empty() {
519 break;
520 }
521
522 let mut search_begin = match last_polled {
525 Some((last_index, last_task_id)) => {
526 let last_index = last_index.min(tasks.len());
531 let last_before_leq = tasks[..last_index]
532 .iter()
533 .rposition(|entry| entry.id <= last_task_id)
534 .unwrap_or(0);
535 match tasks
536 .iter()
537 .enumerate()
538 .skip(last_before_leq)
539 .find(|(_, entry)| entry.id > last_task_id)
540 {
541 Some((index, _)) => index,
542 None => {
543 0
545 }
546 }
547 }
548 None => 0,
549 };
550 let index = loop {
551 match tasks
552 .iter()
553 .enumerate()
554 .skip(search_begin)
555 .find(|(_, entry)| matches!(entry.status, TaskStatus::Runnable))
556 {
557 Some((index, _)) => break Some(index),
558 None => {
559 if search_begin == 0 {
561 break None;
562 }
563 search_begin = 0;
564 }
565 }
566 };
567 let index = index.expect("TestAsyncExecutor stuck with no runnable task.");
568
569 let entry = &mut tasks[index];
570 let task_id = entry.id;
571 last_polled = Some((index, task_id));
572 let mut task = match entry.task.take() {
575 Some(task) => task,
576 None => {
577 continue;
578 }
579 };
580 entry.status = TaskStatus::Blocked;
583 drop(tasks);
586
587 let waker = task::Waker::from(sync::Arc::new(Waker {
588 task_id,
589 executor: this.clone(),
590 }));
591 let mut cx = task::Context::from_waker(&waker);
592 let done = unsafe { task.as_mut().get_unchecked_mut() }.poll_pinned(&mut cx);
594
595 let task = if done {
596 drop(task);
600 None
601 } else {
602 Some(task)
603 };
604
605 let mut tasks = this.tasks.lock();
606 let updated_index = if index < tasks.len() && tasks[index].id == task_id {
609 index
611 } else {
612 match tasks.iter().position(|entry| entry.id == task_id) {
613 Some(updated_index) => updated_index,
614 None => {
615 continue;
618 }
619 }
620 };
621 last_polled = Some((updated_index, task_id));
622
623 if done {
624 let waiter_waker = tasks[updated_index].waiter_waker.take();
625 tasks.remove(updated_index);
626 if let Some(waiter_waker) = waiter_waker {
627 drop(tasks);
628 waiter_waker.wake();
629 }
630 } else {
631 let entry = &mut tasks[updated_index];
632 entry.task = task;
635 }
636 }
637 }
638}
639
640#[test]
641fn test_test_async_executor_simple() {
642 struct SimpleTask {}
643
644 impl future::Future for SimpleTask {
645 type Output = u32;
646
647 fn poll(self: pin::Pin<&mut Self>, _cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
648 task::Poll::Ready(42)
649 }
650 }
651
652 let executor = TestAsyncExecutor::new();
653 let waiter = TestAsyncExecutor::spawn(&executor, SimpleTask {});
654 TestAsyncExecutor::run_to_completion(&executor);
655 assert_eq!(waiter.take().unwrap(), 42);
656 assert_eq!(sync_types::GenericArc::strong_count(&executor), 1);
657 assert_eq!(sync_types::GenericArc::weak_count(&executor), 0);
658
659 let waiter = TestAsyncExecutor::spawn(&executor, async { async { 42 }.await });
660 TestAsyncExecutor::run_to_completion(&executor);
661 assert_eq!(waiter.take().unwrap(), 42);
662 assert_eq!(sync_types::GenericArc::strong_count(&executor), 1);
663 assert_eq!(sync_types::GenericArc::weak_count(&executor), 0);
664}
665
666#[test]
667fn test_test_async_executor_chained_waiters() {
668 struct SimpleTask {}
669
670 impl future::Future for SimpleTask {
671 type Output = u32;
672
673 fn poll(self: pin::Pin<&mut Self>, _cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
674 task::Poll::Ready(42)
675 }
676 }
677
678 let executor = TestAsyncExecutor::new();
679 let waiter = TestAsyncExecutor::spawn(&executor, SimpleTask {});
680 let waiter = TestAsyncExecutor::spawn(&executor, waiter);
681 let waiter = TestAsyncExecutor::spawn(&executor, waiter);
682 TestAsyncExecutor::run_to_completion(&executor);
683 assert_eq!(waiter.take().unwrap(), 42);
684 assert_eq!(sync_types::GenericArc::strong_count(&executor), 1);
685 assert_eq!(sync_types::GenericArc::weak_count(&executor), 0);
686}
687
688#[test]
689fn test_test_async_executor_recursive_spawning() {
690 use ops::DerefMut as _;
691
692 enum SpawningTask {
693 Init {
694 executor: sync_types::GenericArc<TestAsyncExecutor>,
695 n: u32,
696 },
697 WaitingForSpawn {
698 waiter: TestAsyncExecutorTaskWaiter<u32>,
699 },
700 }
701
702 impl Unpin for SpawningTask {}
703
704 impl future::Future for SpawningTask {
705 type Output = u32;
706
707 fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
708 match self.deref_mut() {
709 Self::Init { executor, n } => {
710 if *n == 0 {
711 task::Poll::Ready(0)
712 } else {
713 let mut waiter = TestAsyncExecutor::spawn(
714 executor,
715 SpawningTask::Init {
716 executor: executor.clone(),
717 n: *n - 1,
718 },
719 );
720 match future::Future::poll(pin::Pin::new(&mut waiter), cx) {
721 task::Poll::Ready(_) => {
722 unreachable!();
725 }
726 task::Poll::Pending => {
727 *self.deref_mut() = Self::WaitingForSpawn { waiter };
728 task::Poll::Pending
729 }
730 }
731 }
732 }
733 Self::WaitingForSpawn { waiter } => {
734 match future::Future::poll(pin::Pin::new(waiter), cx) {
735 task::Poll::Ready(n) => task::Poll::Ready(n + 1),
736 task::Poll::Pending => {
737 unreachable!();
740 }
741 }
742 }
743 }
744 }
745 }
746
747 let executor = TestAsyncExecutor::new();
748 let waiter = TestAsyncExecutor::spawn(
749 &executor,
750 SpawningTask::Init {
751 executor: executor.clone(),
752 n: 42,
753 },
754 );
755 TestAsyncExecutor::run_to_completion(&executor);
756 assert_eq!(waiter.take().unwrap(), 42);
757 assert_eq!(sync_types::GenericArc::strong_count(&executor), 1);
758 assert_eq!(sync_types::GenericArc::weak_count(&executor), 0);
759}
760
761#[test]
762fn test_test_async_executor_wake_self() {
763 use ops::Deref as _;
764
765 enum SelfWakingTask {
766 Unpolled,
767 PolledOnce,
768 }
769
770 impl Unpin for SelfWakingTask {}
771
772 impl future::Future for SelfWakingTask {
773 type Output = u32;
774
775 fn poll(mut self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
776 match self.deref() {
777 Self::Unpolled => {
778 cx.waker().wake_by_ref();
779 *self = Self::PolledOnce;
780 task::Poll::Pending
781 }
782 Self::PolledOnce => task::Poll::Ready(42),
783 }
784 }
785 }
786
787 let executor = TestAsyncExecutor::new();
788 let waiter = TestAsyncExecutor::spawn(&executor, SelfWakingTask::Unpolled);
789 let waiter = TestAsyncExecutor::spawn(&executor, waiter);
790 TestAsyncExecutor::run_to_completion(&executor);
791 assert_eq!(waiter.take().unwrap(), 42);
792 assert_eq!(sync_types::GenericArc::strong_count(&executor), 1);
793 assert_eq!(sync_types::GenericArc::weak_count(&executor), 0);
794}