1extern crate alloc;
8use super::broadcast_waker;
9use crate::{
10 alloc::{SyncVec, SyncVecError},
11 sync_types::{self, Lock as _},
12};
13use core::{cell, convert, marker, pin, sync::atomic, task};
14
15#[cfg(doc)]
16use core::future;
17
18pub trait QueuedFuture<T: marker::Send>: marker::Send {
25 type Output: marker::Send;
27 type AuxPollData<'a>;
29
30 fn poll<'a>(
47 self: pin::Pin<&mut Self>,
48 arbitrated_ressource: &mut T,
49 aux_data: &mut Self::AuxPollData<'a>,
50 cx: &mut task::Context<'_>,
51 ) -> task::Poll<Self::Output>;
52}
53
54#[derive(Clone, Copy, Debug)]
56pub enum FutureQueueError {
57 MemoryAllocationFailure,
59}
60
61impl convert::From<broadcast_waker::BroadcastWakerError> for FutureQueueError {
62 fn from(value: broadcast_waker::BroadcastWakerError) -> Self {
63 match value {
64 broadcast_waker::BroadcastWakerError::MemoryAllocationFailure => FutureQueueError::MemoryAllocationFailure,
65 }
66 }
67}
68
69impl convert::From<SyncVecError> for FutureQueueError {
70 fn from(value: SyncVecError) -> Self {
71 match value {
72 SyncVecError::MemoryAllocationFailure => FutureQueueError::MemoryAllocationFailure,
73 }
74 }
75}
76
77pub struct FutureQueue<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> {
112 wakers: broadcast_waker::BroadcastWakerSubscriptions<ST>,
120 state: ST::Lock<FutureQueueState<T, F>>,
122 active_fut: cell::UnsafeCell<Option<F>>,
129 arbitrated_ressource: cell::UnsafeCell<T>,
134}
135
136unsafe impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> marker::Send for FutureQueue<ST, T, F> {}
137unsafe impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> marker::Sync for FutureQueue<ST, T, F> {}
138
139impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> FutureQueue<ST, T, F> {
140 pub fn new(arbitrated_ressource: T) -> Self {
151 Self {
152 wakers: broadcast_waker::BroadcastWakerSubscriptions::new(),
153 state: ST::Lock::from(FutureQueueState::new()),
154 active_fut: cell::UnsafeCell::new(None),
155 arbitrated_ressource: cell::UnsafeCell::new(arbitrated_ressource),
156 }
157 }
158
159 pub fn get_arbitrated_ressource_mut(&mut self) -> &mut T {
162 self.arbitrated_ressource.get_mut()
163 }
164
165 pub fn enqueue<QP: sync_types::SyncRcPtr<FutureQueue<ST, T, F>>>(
181 this: pin::Pin<QP>,
182 fut: F,
183 ) -> Result<EnqueuedFutureSubscription<ST, T, F, QP>, (F, FutureQueueError)> {
184 let queue_entry_id = match this.wakers.subscribe() {
185 Ok(queue_entry_id) => queue_entry_id,
186 Err(e) => return Err((fut, FutureQueueError::from(e))),
187 };
188
189 let state_guard = this.state.lock();
190 let completion_queue_lock =
191 sync_types::LockForInner::<'_, _, _, FutureQueueStateDerefInnerCompletionQueueTag>::from_outer(&this.state);
192 let mut completion_queue_guard =
193 sync_types::LockForInnerGuard::<'_, _, _, FutureQueueStateDerefInnerCompletionQueueTag>::from_outer(
194 state_guard,
195 );
196 let result;
197 (completion_queue_guard, result) =
198 SyncVec::try_reserve_exact(&completion_queue_lock, completion_queue_guard, 1);
199 if let Err(e) = result {
200 this.wakers.unsubscribe(queue_entry_id, false);
201 return Err((fut, FutureQueueError::from(e)));
202 }
203 completion_queue_guard.push(None);
206 let state_guard = completion_queue_guard.into_outer();
207
208 let submission_queue_lock =
209 sync_types::LockForInner::<'_, _, _, FutureQueueStateDerefInnerSubmissionQueueTag>::from_outer(&this.state);
210 let mut submission_queue_guard =
211 sync_types::LockForInnerGuard::<'_, _, _, FutureQueueStateDerefInnerSubmissionQueueTag>::from_outer(
212 state_guard,
213 );
214 let result;
215 (submission_queue_guard, result) =
216 SyncVec::try_reserve_exact(&submission_queue_lock, submission_queue_guard, 1);
217 if let Err(e) = result {
218 let mut state_guard = submission_queue_guard.into_outer();
219 let popped_cqe = state_guard.completion_queue.pop();
220 debug_assert!(matches!(popped_cqe, Some(None)));
221 this.wakers.unsubscribe(queue_entry_id, false);
222 return Err((fut, FutureQueueError::from(e)));
223 }
224 submission_queue_guard.push((queue_entry_id, fut));
225 drop(submission_queue_guard);
226
227 Ok(EnqueuedFutureSubscription::new(this, queue_entry_id))
228 }
229
230 fn cancel_queued(&self, queue_entry_id: broadcast_waker::BroadcastWakerSubscriptionId) {
236 let mut state_guard = self.state.lock();
237 let wake_remaining = if let Some(sqe_index) = state_guard
238 .submission_queue
239 .iter()
240 .position(|sqe| sqe.0 == queue_entry_id)
241 {
242 state_guard.submission_queue.remove(sqe_index);
243
244 debug_assert!(
245 !state_guard
246 .completion_queue
247 .iter()
248 .any(|cqe| cqe.as_ref().map(|cqe| cqe.0 == queue_entry_id).unwrap_or(false))
249 );
250 let popped_cqe = state_guard.completion_queue.pop();
251 debug_assert!(matches!(popped_cqe, Some(None)));
252
253 false
254 } else if state_guard
255 .active_queue_entry_id
256 .map(|active_queue_entry_id| active_queue_entry_id == queue_entry_id)
257 .unwrap_or(false)
258 {
259 state_guard.active_queue_entry_id = None;
266 let wake_remaining = if state_guard.polling_state == FutureQueuePollingState::Idle {
267 let active_fut = self.active_fut.get();
268 let active_fut = unsafe { &mut *active_fut };
270 *active_fut = None;
271 true
275 } else {
276 false
277 };
278
279 debug_assert!(
280 !state_guard
281 .completion_queue
282 .iter()
283 .any(|cqe| cqe.as_ref().map(|cqe| cqe.0 == queue_entry_id).unwrap_or(false))
284 );
285 let popped_cqe = state_guard.completion_queue.pop();
286 debug_assert!(matches!(popped_cqe, Some(None)));
287
288 wake_remaining
289 } else {
290 if let Some(cqe_index) = state_guard
293 .completion_queue
294 .iter()
295 .position(|cqe| cqe.as_ref().map(|cqe| cqe.0 == queue_entry_id).unwrap_or(false))
296 {
297 state_guard.completion_queue.remove(cqe_index);
298 }
299
300 false
301 };
302
303 drop(state_guard);
304 self.wakers.unsubscribe(queue_entry_id, wake_remaining);
305 }
306
307 fn poll_from_queue_entry_owner<
323 'a,
324 QP: 'a + sync_types::SyncRcPtr<Self>,
325 QR: 'a + sync_types::SyncRcPtrRef<'a, Self, QP>,
326 >(
327 this: pin::Pin<QR>,
328 queue_entry_id: broadcast_waker::BroadcastWakerSubscriptionId,
329 aux_poll_data: &mut F::AuxPollData<'_>,
330 cx: &mut task::Context<'_>,
331 ) -> task::Poll<F::Output>
332 where
333 Self: 'a,
334 {
335 let this = unsafe { pin::Pin::into_inner_unchecked(this) };
353
354 let mut state_guard = this.state.lock();
355
356 for (cqe_index, cqe) in state_guard.completion_queue.iter().enumerate() {
359 match cqe {
360 Some(cqe) => {
361 if cqe.0 == queue_entry_id {
362 let cqe = state_guard.completion_queue.remove(cqe_index).unwrap();
364 return task::Poll::Ready(cqe.1);
365 }
366 }
367 None => {
368 break;
370 }
371 }
372 }
373
374 this.wakers.set_subscription_waker(queue_entry_id, cx.waker().clone());
376
377 let mut wake_gen = this.wakers.wake_gen();
394
395 if state_guard.polling_state == FutureQueuePollingState::InPoll {
396 return task::Poll::Pending;
398 }
399 atomic::compiler_fence(atomic::Ordering::Acquire);
404
405 let waker = broadcast_waker::BroadcastWakerSubscriptions::waker(&sync_types::SyncRcPtrRefForInner::<
409 '_,
410 _,
411 _,
412 _,
413 FutureQueueDerefInnerWakersTag,
414 >::new(&this));
415
416 loop {
417 let active_fut = this.active_fut.get();
418 let active_fut = unsafe { &mut *active_fut };
421 let active_fut_entry = if state_guard.active_queue_entry_id.is_some() {
422 active_fut.as_mut().unwrap()
423 } else {
424 *active_fut = None;
426 debug_assert!(!state_guard.submission_queue.is_empty());
429 let head_sqe = state_guard.submission_queue.remove(0);
430 state_guard.active_queue_entry_id = Some(head_sqe.0);
431 active_fut.insert(head_sqe.1)
432 };
433
434 let in_poll_guard = FutureQueueInPollGuard::new(&this, state_guard);
440
441 let f = unsafe { pin::Pin::new_unchecked(active_fut_entry) };
443 let arbitrated_ressource = this.arbitrated_ressource.get();
444 let arbitrated_ressource = unsafe { &mut *arbitrated_ressource };
446
447 let result = QueuedFuture::poll(
448 f,
449 arbitrated_ressource,
450 aux_poll_data,
451 &mut task::Context::from_waker(&waker),
452 );
453
454 state_guard = in_poll_guard.release();
467
468 let completed_queue_entry_id = match state_guard.active_queue_entry_id {
469 Some(active_queue_entry_id) => active_queue_entry_id,
470 None => {
471 *active_fut = None;
473 wake_gen = this.wakers.wake_gen();
475 continue;
476 }
477 };
478
479 match result {
480 task::Poll::Ready(result) => {
481 state_guard.active_queue_entry_id = None;
482 *active_fut = None;
483 if completed_queue_entry_id == queue_entry_id {
484 let popped_cqe = state_guard.completion_queue.pop();
488 debug_assert!(matches!(popped_cqe, Some(None)));
489 drop(state_guard);
490 this.wakers.unsubscribe(queue_entry_id, true);
492 return task::Poll::Ready(result);
493 } else {
494 let cqe = state_guard
495 .completion_queue
496 .iter_mut()
497 .find(|cqe| cqe.is_none())
498 .unwrap();
499 *cqe = Some((completed_queue_entry_id, result));
500 let completed_waker = this.wakers.unsubscribe(completed_queue_entry_id, false).flatten();
501 if let Some(completed_waker) = completed_waker {
502 completed_waker.wake();
503 }
504 wake_gen = this.wakers.wake_gen();
506 }
507 }
508 task::Poll::Pending => {
509 let cur_wake_gen = this.wakers.wake_gen();
510 if wake_gen != cur_wake_gen {
511 wake_gen = cur_wake_gen;
514 } else {
515 return task::Poll::Pending;
516 }
517 }
518 }
519 }
520 }
521}
522
523struct FutureQueueDerefInnerWakersTag {}
530
531impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>>
532 sync_types::DerefInnerByTag<FutureQueueDerefInnerWakersTag> for FutureQueue<ST, T, F>
533{
534 crate::impl_deref_inner_by_tag!(wakers, broadcast_waker::BroadcastWakerSubscriptions<ST>);
535}
536
537impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>>
538 sync_types::DerefMutInnerByTag<FutureQueueDerefInnerWakersTag> for FutureQueue<ST, T, F>
539{
540 crate::impl_deref_mut_inner_by_tag!(wakers);
541}
542
543struct FutureQueueState<T: marker::Send, F: QueuedFuture<T>> {
545 polling_state: FutureQueuePollingState,
546 submission_queue: SyncVec<(broadcast_waker::BroadcastWakerSubscriptionId, F)>,
550 completion_queue: SyncVec<Option<(broadcast_waker::BroadcastWakerSubscriptionId, F::Output)>>,
557 active_queue_entry_id: Option<broadcast_waker::BroadcastWakerSubscriptionId>,
564}
565
566impl<T: marker::Send, F: QueuedFuture<T>> FutureQueueState<T, F> {
567 fn new() -> Self {
568 Self {
569 polling_state: FutureQueuePollingState::Idle,
570 submission_queue: SyncVec::new(),
571 completion_queue: SyncVec::new(),
572 active_queue_entry_id: None,
573 }
574 }
575}
576
577#[derive(PartialEq, Eq)]
594enum FutureQueuePollingState {
595 Idle,
597 InPoll,
601}
602
603struct FutureQueueInPollGuard<'a, ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> {
609 queue: &'a FutureQueue<ST, T, F>,
610 locked_in_poll: bool,
611}
612
613impl<'a, ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> FutureQueueInPollGuard<'a, ST, T, F> {
614 fn new<'b>(
631 queue: &'a FutureQueue<ST, T, F>,
632 mut state_guard: <ST::Lock<FutureQueueState<T, F>> as sync_types::Lock<FutureQueueState<T, F>>>::Guard<'b>,
633 ) -> Self {
634 state_guard.polling_state = FutureQueuePollingState::InPoll;
635 Self {
636 queue,
637 locked_in_poll: true,
638 }
639 }
640
641 fn release(mut self) -> <ST::Lock<FutureQueueState<T, F>> as sync_types::Lock<FutureQueueState<T, F>>>::Guard<'a> {
655 let mut state_guard = self.queue.state.lock();
656 state_guard.polling_state = FutureQueuePollingState::Idle;
657 self.locked_in_poll = false;
658 state_guard
659 }
660}
661
662impl<'a, ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>> Drop for FutureQueueInPollGuard<'a, ST, T, F> {
663 fn drop(&mut self) {
664 if self.locked_in_poll {
665 self.queue.state.lock().polling_state = FutureQueuePollingState::Idle;
666 self.locked_in_poll = false;
667 }
668 }
669}
670
671struct FutureQueueStateDerefInnerSubmissionQueueTag;
679
680impl<T: marker::Send, F: QueuedFuture<T>> sync_types::DerefInnerByTag<FutureQueueStateDerefInnerSubmissionQueueTag>
681 for FutureQueueState<T, F>
682{
683 crate::impl_deref_inner_by_tag!(
684 submission_queue,
685 SyncVec<(broadcast_waker::BroadcastWakerSubscriptionId, F)>
686 );
687}
688
689impl<T: marker::Send, F: QueuedFuture<T>> sync_types::DerefMutInnerByTag<FutureQueueStateDerefInnerSubmissionQueueTag>
690 for FutureQueueState<T, F>
691{
692 crate::impl_deref_mut_inner_by_tag!(submission_queue);
693}
694
695struct FutureQueueStateDerefInnerCompletionQueueTag;
703
704impl<T: marker::Send, F: QueuedFuture<T>> sync_types::DerefInnerByTag<FutureQueueStateDerefInnerCompletionQueueTag>
705 for FutureQueueState<T, F>
706{
707 crate::impl_deref_inner_by_tag!(
708 completion_queue,
709 SyncVec<Option<(broadcast_waker::BroadcastWakerSubscriptionId, F::Output,)>>
710 );
711}
712
713impl<T: marker::Send, F: QueuedFuture<T>> sync_types::DerefMutInnerByTag<FutureQueueStateDerefInnerCompletionQueueTag>
714 for FutureQueueState<T, F>
715{
716 crate::impl_deref_mut_inner_by_tag!(completion_queue);
717}
718
719pub struct EnqueuedFutureSubscription<
729 ST: sync_types::SyncTypes,
730 T: marker::Send,
731 F: QueuedFuture<T>,
732 QP: sync_types::SyncRcPtr<FutureQueue<ST, T, F>>,
733> {
734 state: EnqueuedFutureSubscriptionState<ST, T, F, QP>,
735}
736
737impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>, QP: sync_types::SyncRcPtr<FutureQueue<ST, T, F>>>
738 EnqueuedFutureSubscription<ST, T, F, QP>
739{
740 fn new(queue: pin::Pin<QP>, queue_entry_id: broadcast_waker::BroadcastWakerSubscriptionId) -> Self {
747 Self {
748 state: EnqueuedFutureSubscriptionState::Pending {
749 queue,
750 queue_entry_id,
751 _phantom: marker::PhantomData,
752 },
753 }
754 }
755
756 pub fn poll(
779 &mut self,
780 aux_poll_data: &mut F::AuxPollData<'_>,
781 cx: &mut task::Context<'_>,
782 ) -> task::Poll<F::Output> {
783 match &self.state {
784 EnqueuedFutureSubscriptionState::Pending {
785 queue,
786 queue_entry_id,
787 _phantom,
788 } => {
789 let result = FutureQueue::poll_from_queue_entry_owner(
790 sync_types::SyncRcPtr::as_ref(queue),
791 *queue_entry_id,
792 aux_poll_data,
793 cx,
794 );
795 if matches!(result, task::Poll::Ready(_)) {
796 self.state = EnqueuedFutureSubscriptionState::Done;
797 }
798 result
799 }
800 EnqueuedFutureSubscriptionState::Done => unreachable!(),
801 }
802 }
803}
804
805impl<ST: sync_types::SyncTypes, T: marker::Send, F: QueuedFuture<T>, QP: sync_types::SyncRcPtr<FutureQueue<ST, T, F>>>
806 Drop for EnqueuedFutureSubscription<ST, T, F, QP>
807{
808 fn drop(&mut self) {
809 match &self.state {
810 EnqueuedFutureSubscriptionState::Pending {
811 queue,
812 queue_entry_id,
813 _phantom,
814 } => {
815 queue.cancel_queued(*queue_entry_id);
816 self.state = EnqueuedFutureSubscriptionState::Done;
817 }
818 EnqueuedFutureSubscriptionState::Done => (),
819 }
820 }
821}
822
823enum EnqueuedFutureSubscriptionState<
825 ST: sync_types::SyncTypes,
826 T: marker::Send,
827 F: QueuedFuture<T>,
828 QP: sync_types::SyncRcPtr<FutureQueue<ST, T, F>>,
829> {
830 Pending {
833 queue: pin::Pin<QP>,
835 queue_entry_id: broadcast_waker::BroadcastWakerSubscriptionId,
837 #[allow(clippy::type_complexity)]
838 _phantom: marker::PhantomData<fn() -> (*const ST, *const T, *const F)>,
839 },
840 Done,
841}
842
843#[test]
844fn test_future_queue_poll_in_order() {
845 use crate::test::{TestAsyncExecutor, TestNopSyncTypes};
846 use core::future;
847
848 type TestFutureQueueArbitratedRessourceType = u32;
849
850 struct TestQueuedFuture {}
851
852 impl QueuedFuture<TestFutureQueueArbitratedRessourceType> for TestQueuedFuture {
853 type Output = u32;
854 type AuxPollData<'a> = ();
855
856 fn poll<'a>(
857 self: pin::Pin<&mut Self>,
858 arbitrated_ressource: &mut TestFutureQueueArbitratedRessourceType,
859 _aux_data: &mut Self::AuxPollData<'a>,
860 _cx: &mut task::Context<'_>,
861 ) -> task::Poll<Self::Output> {
862 *arbitrated_ressource += 1;
863 task::Poll::Ready(*arbitrated_ressource)
864 }
865 }
866
867 type TestFutureQueue = FutureQueue<TestNopSyncTypes, TestFutureQueueArbitratedRessourceType, TestQueuedFuture>;
868 type TestFutureQueueSyncRcPtr =
869 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::SyncRcPtr<
870 TestFutureQueue,
871 >;
872 type TestEnqueuedFutureSubscription = EnqueuedFutureSubscription<
873 TestNopSyncTypes,
874 TestFutureQueueArbitratedRessourceType,
875 TestQueuedFuture,
876 TestFutureQueueSyncRcPtr,
877 >;
878
879 struct TestWrapEnqueuedFuture {
880 enqueued_future: TestEnqueuedFutureSubscription,
881 }
882
883 impl future::Future for TestWrapEnqueuedFuture {
884 type Output = <TestQueuedFuture as QueuedFuture<TestFutureQueueArbitratedRessourceType>>::Output;
885
886 fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
887 self.get_mut().enqueued_future.poll(&mut (), cx)
888 }
889 }
890
891 let queue =
892 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::try_new(
893 FutureQueue::<TestNopSyncTypes, u32, TestQueuedFuture>::new(0),
894 )
895 .unwrap();
896 let queue = unsafe { pin::Pin::new_unchecked(queue) };
897
898 let enqueued0 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
899 .map_err(|(_f, e)| e)
900 .unwrap();
901 let enqueued1 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
902 .map_err(|(_f, e)| e)
903 .unwrap();
904 let enqueued2 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
905 .map_err(|(_f, e)| e)
906 .unwrap();
907
908 let e = TestAsyncExecutor::new();
909 let w0 = TestAsyncExecutor::spawn(
910 &e,
911 TestWrapEnqueuedFuture {
912 enqueued_future: enqueued0,
913 },
914 );
915 let w1 = TestAsyncExecutor::spawn(
916 &e,
917 TestWrapEnqueuedFuture {
918 enqueued_future: enqueued1,
919 },
920 );
921 let w2 = TestAsyncExecutor::spawn(
922 &e,
923 TestWrapEnqueuedFuture {
924 enqueued_future: enqueued2,
925 },
926 );
927 TestAsyncExecutor::run_to_completion(&e);
928
929 assert_eq!(w0.take().unwrap(), 1);
930 assert_eq!(w1.take().unwrap(), 2);
931 assert_eq!(w2.take().unwrap(), 3);
932}
933
934#[test]
935fn test_future_queue_poll_in_reverse_order() {
936 use crate::test::{TestAsyncExecutor, TestNopSyncTypes};
937 use core::future;
938
939 type TestFutureQueueArbitratedRessourceType = u32;
940
941 struct TestQueuedFuture {}
942
943 impl QueuedFuture<TestFutureQueueArbitratedRessourceType> for TestQueuedFuture {
944 type Output = u32;
945 type AuxPollData<'a> = ();
946
947 fn poll<'a>(
948 self: pin::Pin<&mut Self>,
949 arbitrated_ressource: &mut TestFutureQueueArbitratedRessourceType,
950 _aux_data: &mut Self::AuxPollData<'a>,
951 _cx: &mut task::Context<'_>,
952 ) -> task::Poll<Self::Output> {
953 *arbitrated_ressource += 1;
954 task::Poll::Ready(*arbitrated_ressource)
955 }
956 }
957
958 type TestFutureQueue = FutureQueue<TestNopSyncTypes, TestFutureQueueArbitratedRessourceType, TestQueuedFuture>;
959 type TestFutureQueueSyncRcPtr =
960 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::SyncRcPtr<
961 TestFutureQueue,
962 >;
963 type TestEnqueuedFutureSubscription = EnqueuedFutureSubscription<
964 TestNopSyncTypes,
965 TestFutureQueueArbitratedRessourceType,
966 TestQueuedFuture,
967 TestFutureQueueSyncRcPtr,
968 >;
969
970 struct TestWrapEnqueuedFuture {
971 enqueued_future: TestEnqueuedFutureSubscription,
972 }
973
974 impl future::Future for TestWrapEnqueuedFuture {
975 type Output = <TestQueuedFuture as QueuedFuture<TestFutureQueueArbitratedRessourceType>>::Output;
976
977 fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
978 self.get_mut().enqueued_future.poll(&mut (), cx)
979 }
980 }
981
982 let queue =
983 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::try_new(
984 FutureQueue::<TestNopSyncTypes, u32, TestQueuedFuture>::new(0),
985 )
986 .unwrap();
987 let queue = unsafe { pin::Pin::new_unchecked(queue) };
988
989 let enqueued0 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
990 .map_err(|(_f, e)| e)
991 .unwrap();
992 let enqueued1 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
993 .map_err(|(_f, e)| e)
994 .unwrap();
995 let enqueued2 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
996 .map_err(|(_f, e)| e)
997 .unwrap();
998
999 let e = TestAsyncExecutor::new();
1000 let w2 = TestAsyncExecutor::spawn(
1001 &e,
1002 TestWrapEnqueuedFuture {
1003 enqueued_future: enqueued2,
1004 },
1005 );
1006 TestAsyncExecutor::run_to_completion(&e);
1007 assert_eq!(w2.take().unwrap(), 3);
1008
1009 let w1 = TestAsyncExecutor::spawn(
1010 &e,
1011 TestWrapEnqueuedFuture {
1012 enqueued_future: enqueued1,
1013 },
1014 );
1015 TestAsyncExecutor::run_to_completion(&e);
1016 assert_eq!(w1.take().unwrap(), 2);
1017
1018 let w0 = TestAsyncExecutor::spawn(
1019 &e,
1020 TestWrapEnqueuedFuture {
1021 enqueued_future: enqueued0,
1022 },
1023 );
1024 TestAsyncExecutor::run_to_completion(&e);
1025 assert_eq!(w0.take().unwrap(), 1);
1026}
1027
1028#[test]
1029fn test_future_queue_cancel_queued() {
1030 use crate::test::{TestAsyncExecutor, TestNopSyncTypes};
1031 use core::future;
1032
1033 type TestFutureQueueArbitratedRessourceType = u32;
1034
1035 struct TestQueuedFuture {}
1036
1037 impl QueuedFuture<TestFutureQueueArbitratedRessourceType> for TestQueuedFuture {
1038 type Output = u32;
1039 type AuxPollData<'a> = ();
1040
1041 fn poll<'a>(
1042 self: pin::Pin<&mut Self>,
1043 arbitrated_ressource: &mut TestFutureQueueArbitratedRessourceType,
1044 _aux_data: &mut Self::AuxPollData<'a>,
1045 _cx: &mut task::Context<'_>,
1046 ) -> task::Poll<Self::Output> {
1047 *arbitrated_ressource += 1;
1048 task::Poll::Ready(*arbitrated_ressource)
1049 }
1050 }
1051
1052 type TestFutureQueue = FutureQueue<TestNopSyncTypes, TestFutureQueueArbitratedRessourceType, TestQueuedFuture>;
1053 type TestFutureQueueSyncRcPtr =
1054 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::SyncRcPtr<
1055 TestFutureQueue,
1056 >;
1057 type TestEnqueuedFutureSubscription = EnqueuedFutureSubscription<
1058 TestNopSyncTypes,
1059 TestFutureQueueArbitratedRessourceType,
1060 TestQueuedFuture,
1061 TestFutureQueueSyncRcPtr,
1062 >;
1063
1064 struct TestCancelQueuedFuture {
1065 enqueued0: TestEnqueuedFutureSubscription,
1066 enqueued1: Option<TestEnqueuedFutureSubscription>,
1067 enqueued2: TestEnqueuedFutureSubscription,
1068 }
1069
1070 impl future::Future for TestCancelQueuedFuture {
1071 type Output = ();
1072
1073 fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<()> {
1074 let this = self.get_mut();
1075 drop(this.enqueued1.take());
1076 assert_eq!(this.enqueued2.poll(&mut (), cx), task::Poll::Ready(2));
1077 assert_eq!(this.enqueued0.poll(&mut (), cx), task::Poll::Ready(1));
1078 task::Poll::Ready(())
1079 }
1080 }
1081
1082 let queue =
1083 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::try_new(
1084 FutureQueue::<TestNopSyncTypes, u32, TestQueuedFuture>::new(0),
1085 )
1086 .unwrap();
1087 let queue = unsafe { pin::Pin::new_unchecked(queue) };
1088
1089 let enqueued0 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
1090 .map_err(|(_f, e)| e)
1091 .unwrap();
1092 let enqueued1 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
1093 .map_err(|(_f, e)| e)
1094 .unwrap();
1095 let enqueued2 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture {})
1096 .map_err(|(_f, e)| e)
1097 .unwrap();
1098
1099 let e = TestAsyncExecutor::new();
1100 let w = TestAsyncExecutor::spawn(
1101 &e,
1102 TestCancelQueuedFuture {
1103 enqueued0,
1104 enqueued1: Some(enqueued1),
1105 enqueued2,
1106 },
1107 );
1108 TestAsyncExecutor::run_to_completion(&e);
1109 w.take().unwrap();
1110}
1111
1112#[test]
1113fn test_future_queue_cancel_active() {
1114 use crate::test::{TestAsyncExecutor, TestNopSyncTypes};
1115 use core::future;
1116
1117 type TestFutureQueueArbitratedRessourceType = u32;
1118
1119 struct TestQueuedFuture {
1120 stall_forever: bool,
1121 }
1122
1123 impl QueuedFuture<TestFutureQueueArbitratedRessourceType> for TestQueuedFuture {
1124 type Output = u32;
1125 type AuxPollData<'a> = ();
1126
1127 fn poll<'a>(
1128 self: pin::Pin<&mut Self>,
1129 arbitrated_ressource: &mut TestFutureQueueArbitratedRessourceType,
1130 _aux_data: &mut Self::AuxPollData<'a>,
1131 _cx: &mut task::Context<'_>,
1132 ) -> task::Poll<Self::Output> {
1133 if self.stall_forever {
1134 return task::Poll::Pending;
1135 }
1136 *arbitrated_ressource += 1;
1137 task::Poll::Ready(*arbitrated_ressource)
1138 }
1139 }
1140
1141 type TestFutureQueue = FutureQueue<TestNopSyncTypes, TestFutureQueueArbitratedRessourceType, TestQueuedFuture>;
1142 type TestFutureQueueSyncRcPtr =
1143 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::SyncRcPtr<
1144 TestFutureQueue,
1145 >;
1146 type TestEnqueuedFutureSubscription = EnqueuedFutureSubscription<
1147 TestNopSyncTypes,
1148 TestFutureQueueArbitratedRessourceType,
1149 TestQueuedFuture,
1150 TestFutureQueueSyncRcPtr,
1151 >;
1152
1153 struct TestCancelQueuedFuture {
1154 enqueued0: Option<TestEnqueuedFutureSubscription>,
1155 enqueued1: TestEnqueuedFutureSubscription,
1156 enqueued2: TestEnqueuedFutureSubscription,
1157 }
1158
1159 impl future::Future for TestCancelQueuedFuture {
1160 type Output = ();
1161
1162 fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<()> {
1163 let this = self.get_mut();
1164 assert_eq!(this.enqueued0.as_mut().unwrap().poll(&mut (), cx), task::Poll::Pending);
1165 assert_eq!(this.enqueued1.poll(&mut (), cx), task::Poll::Pending);
1166 assert_eq!(this.enqueued2.poll(&mut (), cx), task::Poll::Pending);
1167 drop(this.enqueued0.take());
1168 assert_eq!(this.enqueued2.poll(&mut (), cx), task::Poll::Ready(2));
1169 assert_eq!(this.enqueued1.poll(&mut (), cx), task::Poll::Ready(1));
1170 task::Poll::Ready(())
1171 }
1172 }
1173
1174 let queue =
1175 <<TestNopSyncTypes as sync_types::SyncTypes>::SyncRcPtrFactory as sync_types::SyncRcPtrFactory>::try_new(
1176 FutureQueue::<TestNopSyncTypes, u32, TestQueuedFuture>::new(0),
1177 )
1178 .unwrap();
1179 let queue = unsafe { pin::Pin::new_unchecked(queue) };
1180
1181 let enqueued0 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture { stall_forever: true })
1182 .map_err(|(_f, e)| e)
1183 .unwrap();
1184 let enqueued1 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture { stall_forever: false })
1185 .map_err(|(_f, e)| e)
1186 .unwrap();
1187 let enqueued2 = FutureQueue::enqueue(queue.clone(), TestQueuedFuture { stall_forever: false })
1188 .map_err(|(_f, e)| e)
1189 .unwrap();
1190
1191 let e = TestAsyncExecutor::new();
1192 let w = TestAsyncExecutor::spawn(
1193 &e,
1194 TestCancelQueuedFuture {
1195 enqueued0: Some(enqueued0),
1196 enqueued1,
1197 enqueued2,
1198 },
1199 );
1200 TestAsyncExecutor::run_to_completion(&e);
1201 w.take().unwrap();
1202}