1mod id;
2pub mod iter;
3mod waker;
4mod wrappers;
5
6use std::{
7 cell::Cell,
8 fmt,
9 ops::{ControlFlow, Index, IndexMut, Not},
10 pin::Pin,
11 rc::Rc,
12 sync::{Arc, Weak},
13 task::{Context, Poll},
14};
15
16use futures::Stream;
17
18use crate::{
19 list::{self, List, Node},
20 queue::Receiver,
21 selector::{iter::ExtractIf, waker::NodeWaker},
22 task::Task,
23};
24
25pub use crate::selector::{
26 id::Id,
27 wrappers::{Borrowed, BorrowedMut, Removed},
28};
29
30pub struct Selector<T, S> {
72 queue: Receiver<list::ListProtected<T>>,
74 list: List<T>,
76 strategy: S,
78}
79
80impl<T, S> Selector<T, S> {
81 pub fn new(strategy: S) -> Self {
83 Self {
84 queue: Default::default(),
85 list: Default::default(),
86 strategy,
87 }
88 }
89
90 pub fn push(&mut self, task: T) -> BorrowedMut<'_, T> {
96 BorrowedMut(self.list.push_back(self.queue.queue(), task))
97 }
98
99 pub fn len(&self) -> usize {
103 self.list.len()
104 }
105
106 pub fn is_empty(&self) -> bool {
110 self.list.is_empty()
111 }
112
113 pub fn contains(&self, id: &Id<T>) -> bool {
117 self.get(id).is_some()
118 }
119
120 pub fn get<'a>(&'a self, id: &Id<T>) -> Option<Borrowed<'a, T>> {
124 if self.created(id.get()).not() {
125 return None;
126 }
127 unsafe { self.list.get(id.get()).map(Borrowed) }
128 }
129
130 pub fn get_mut<'a>(&'a mut self, id: &Id<T>) -> Option<BorrowedMut<'a, T>> {
134 if self.created(id.get()).not() {
135 return None;
136 }
137 unsafe { self.list.get_mut(id.get()).map(BorrowedMut) }
138 }
139
140 pub fn remove(&mut self, id: &Id<T>) -> Option<Removed<T>> {
144 if self.created(id.get()).not() {
145 return None;
146 }
147 unsafe { self.list.remove(id.get()).map(Removed) }
148 }
149
150 pub fn strategy(&self) -> &S {
152 &self.strategy
153 }
154
155 pub fn strategy_mut(&mut self) -> &mut S {
157 &mut self.strategy
158 }
159
160 pub fn with_strategy<S1>(self, strategy: S1) -> Selector<T, S1> {
162 Selector {
163 queue: self.queue,
164 list: self.list,
165 strategy,
166 }
167 }
168
169 pub fn iter(&self) -> iter::Iter<'_, T> {
173 iter::Iter(self.list.cursor())
174 }
175
176 pub fn iter_mut(&mut self) -> iter::IterMut<'_, T> {
180 iter::IterMut(self.list.cursor_mut())
181 }
182
183 #[must_use = "ExtractIf does not remove any elements unless consumed"]
191 pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, T, F>
192 where
193 F: for<'b> FnMut(BorrowedMut<'b, T>) -> bool,
194 {
195 ExtractIf {
196 cursor: self.list.cursor_mut(),
197 pred,
198 }
199 }
200
201 pub fn retain<F>(&mut self, mut pred: F)
206 where
207 F: for<'b> FnMut(BorrowedMut<'b, T>) -> bool,
208 {
209 for _ in self.extract_if(|borrowed| pred(borrowed).not()) {}
210 }
211
212 pub fn wake_all(&self) {
214 self.iter().for_each(|task| task.id().wake());
215 }
216
217 fn created(&self, task: &Node<T>) -> bool {
218 let this_queue_ptr = Arc::as_ptr(self.queue.queue());
219 let task_queue_ptr = Weak::as_ptr(task.queue());
220 this_queue_ptr == task_queue_ptr
221 }
222}
223
224impl<T, S> Extend<T> for Selector<T, S> {
225 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
226 for task in iter {
227 self.push(task);
228 }
229 }
230}
231
232impl<T, S> FromIterator<T> for Selector<T, S>
233where
234 S: Default,
235{
236 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
237 let mut this = Self::default();
238 this.extend(iter);
239 this
240 }
241}
242
243impl<T, S> IntoIterator for Selector<T, S> {
244 type IntoIter = iter::IntoIter<T>;
245 type Item = Removed<T>;
246
247 fn into_iter(self) -> Self::IntoIter {
248 iter::IntoIter(self.list)
249 }
250}
251
252impl<'a, T, S> IntoIterator for &'a Selector<T, S> {
253 type IntoIter = iter::Iter<'a, T>;
254 type Item = Borrowed<'a, T>;
255
256 fn into_iter(self) -> Self::IntoIter {
257 self.iter()
258 }
259}
260
261impl<'a, T, S> IntoIterator for &'a mut Selector<T, S> {
262 type IntoIter = iter::IterMut<'a, T>;
263 type Item = BorrowedMut<'a, T>;
264
265 fn into_iter(self) -> Self::IntoIter {
266 self.iter_mut()
267 }
268}
269
270impl<T, S> Stream for Selector<T, S>
271where
272 T: Task<S>,
273 S: Unpin,
274{
275 type Item = T::Output;
276
277 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
278 let this = self.get_mut();
279
280 let marker = this.queue.register_waker(cx.waker());
281 if marker.is_null() {
282 return if this.list.is_empty() {
283 Poll::Ready(None)
284 } else {
285 Poll::Pending
286 };
287 }
288
289 while let Some(node) = this.queue.dequeue() {
290 let is_last = Arc::as_ptr(node.get()) == marker;
291
292 let guard = unsafe { this.list.access(node.get()) };
293 let Some(mut guard) = guard else {
294 if is_last {
295 break;
296 } else {
297 continue;
298 }
299 };
300
301 let node = node.into_inner();
302
303 let result = {
304 let waker = NodeWaker::new(&node);
305 guard
306 .borrow_mut()
307 .get_pin_mut()
308 .poll_progress(&mut this.strategy, &mut Context::from_waker(&waker))
309 };
310
311 match result {
312 Poll::Ready(ControlFlow::Continue(val)) => {
313 unsafe {
314 this.queue.queue().enqueue(node);
316 }
317 let output =
318 T::transform_cont(BorrowedMut(guard.borrow_mut()), &mut this.strategy, val);
319 guard.forget();
320 if output.is_some() {
321 return Poll::Ready(output);
322 }
323 }
324
325 Poll::Ready(ControlFlow::Break(val)) => {
326 let node = guard.remove_now();
327 let output = T::transform_break(Removed(node), &mut this.strategy, val);
328 if output.is_some() {
329 return Poll::Ready(output);
330 }
331 }
332
333 Poll::Pending => {
334 guard.forget();
335 }
336 }
337
338 if is_last {
339 break;
340 }
341 }
342
343 if this.list.is_empty() {
344 Poll::Ready(None)
345 } else {
346 Poll::Pending
347 }
348 }
349
350 fn size_hint(&self) -> (usize, Option<usize>) {
351 (0, self.list.is_empty().then_some(0))
352 }
353}
354
355impl<T, S> Default for Selector<T, S>
356where
357 S: Default,
358{
359 fn default() -> Self {
360 Self::new(Default::default())
361 }
362}
363
364impl<T, S> fmt::Debug for Selector<T, S>
365where
366 S: fmt::Debug,
367{
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 f.debug_struct("Selector")
370 .field("tasks", &self.list.len())
371 .field("strategy", &self.strategy)
372 .field("queue_ptr", &Arc::as_ptr(self.queue.queue()))
373 .finish_non_exhaustive()
374 }
375}
376
377impl<T, S> Index<&Id<T>> for Selector<T, S> {
378 type Output = T;
379
380 fn index(&self, id: &Id<T>) -> &Self::Output {
381 self.get(id).expect("task not found").into_pin().get_ref()
382 }
383}
384
385impl<T, S> Index<Id<T>> for Selector<T, S> {
386 type Output = T;
387
388 fn index(&self, id: Id<T>) -> &Self::Output {
389 &self[&id]
390 }
391}
392
393impl<T, S> IndexMut<&Id<T>> for Selector<T, S>
394where
395 T: Unpin,
396{
397 fn index_mut(&mut self, id: &Id<T>) -> &mut Self::Output {
398 self.get_mut(id)
399 .expect("task not found")
400 .into_pin_mut()
401 .get_mut()
402 }
403}
404
405impl<T, S> IndexMut<Id<T>> for Selector<T, S>
406where
407 T: Unpin,
408{
409 fn index_mut(&mut self, id: Id<T>) -> &mut Self::Output {
410 &mut self[&id]
411 }
412}
413
414unsafe impl<T, S> Send for Selector<T, S>
415where
416 T: Send,
417 S: Send,
418{
419}
420
421unsafe impl<T, S> Sync for Selector<T, S>
422where
423 T: Sync,
424 S: Sync,
425{
426}
427
428static_assertions::assert_impl_all!(Selector<(), ()>: Send, Sync);
429static_assertions::assert_impl_all!(Selector<Cell<()>, Cell<()>>: Send);
430static_assertions::assert_not_impl_any!(Selector<Cell<()>, ()>: Sync);
431static_assertions::assert_not_impl_any!(Selector<(), Cell<()>>: Sync);
432static_assertions::assert_not_impl_any!(Selector<Rc<()>, ()>: Send, Sync);
433static_assertions::assert_not_impl_any!(Selector<(), Rc<()>>: Send, Sync);
434
435#[cfg(test)]
436mod test {
437 use std::{
438 ops::ControlFlow,
439 panic::AssertUnwindSafe,
440 pin::Pin,
441 sync::Arc,
442 task::{Context, Poll, Waker},
443 };
444
445 use futures::{FutureExt, StreamExt};
446
447 use crate::{
448 FutureSelector, StreamSelector,
449 selector::{BorrowedMut, Removed, Selector},
450 task::Task,
451 };
452
453 #[test]
454 fn retain_removes_correct_tasks() {
455 let mut selector = (-3_i32..=3).collect::<FutureSelector<_>>();
456 selector.retain(|task| task.is_positive());
457 let retained = selector
458 .into_iter()
459 .map(Removed::into_inner)
460 .collect::<Vec<_>>();
461 assert_eq!(retained, &[1, 2, 3],);
462 }
463
464 #[test]
465 fn extract_if_removes_correct_tasks() {
466 let mut selector = (-3_i32..=3).collect::<FutureSelector<_>>();
467 let iter = selector.extract_if(|task| task.is_positive());
468 assert_eq!(
469 iter.map(Removed::into_inner).collect::<Vec<_>>(),
470 vec![1, 2, 3],
471 );
472 let retained = selector
473 .into_iter()
474 .map(Removed::into_inner)
475 .collect::<Vec<_>>();
476 assert_eq!(retained, &[-3, -2, -1, 0],);
477 }
478
479 #[test]
480 fn extract_if_retains_tasks_when_dropped() {
481 let mut selector = (-3_i32..=3).collect::<FutureSelector<_>>();
482 let iter = selector.extract_if(|task| task.is_positive());
483 assert_eq!(
484 iter.take(1).map(Removed::into_inner).collect::<Vec<_>>(),
485 vec![1],
486 );
487 let retained = selector
488 .into_iter()
489 .map(Removed::into_inner)
490 .collect::<Vec<_>>();
491 assert_eq!(retained, &[-3, -2, -1, 0, 2, 3],);
492 }
493
494 #[test]
495 fn single_selector_poll_polls_each_task_at_most_once() {
496 #[derive(Clone)]
497 struct Task(usize);
498
499 impl Future for Task {
500 type Output = ();
501
502 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
503 let this = self.get_mut();
504 this.0 += 1;
505 cx.waker().wake_by_ref();
506 Poll::Pending
507 }
508 }
509
510 let mut selector = std::iter::repeat_n(Task(0), 3).collect::<FutureSelector<_>>();
511 for i in 0..=3 {
512 selector
513 .iter()
514 .for_each(|borrowed| assert_eq!(borrowed.get_pin().0, i));
515 assert!(
516 selector
517 .poll_next_unpin(&mut Context::from_waker(Waker::noop()))
518 .is_pending()
519 );
520 }
521 }
522
523 #[tokio::test]
524 async fn selector_respects_strategy_and_round_robin_order() {
525 #[derive(Clone)]
526 struct MyTask(usize);
527
528 impl Task for MyTask {
529 type Cont = usize;
530 type Break = usize;
531 type Output = usize;
532
533 fn poll_progress(
534 self: Pin<&mut Self>,
535 _: &mut (),
536 _: &mut Context<'_>,
537 ) -> Poll<ControlFlow<Self::Break, Self::Cont>> {
538 let state = self.get_mut();
539 state.0 += 1;
540 if state.0 > 5 {
541 Poll::Ready(ControlFlow::Break(state.0))
542 } else {
543 Poll::Ready(ControlFlow::Continue(state.0))
544 }
545 }
546
547 fn transform_cont(
548 _: BorrowedMut<'_, Self>,
549 _: &mut (),
550 value: Self::Cont,
551 ) -> Option<Self::Output> {
552 value.is_power_of_two().then_some(value)
553 }
554
555 fn transform_break(
556 _: Removed<Self>,
557 _: &mut (),
558 value: Self::Break,
559 ) -> Option<Self::Output> {
560 Some(value * 2)
561 }
562 }
563
564 let selector = std::iter::repeat_n(MyTask(0), 3).collect::<Selector<_, ()>>();
565 let results = selector.collect::<Vec<_>>().await;
566 assert_eq!(results, vec![1, 1, 1, 2, 2, 2, 4, 4, 4, 12, 12, 12],);
567 }
568
569 #[tokio::test]
570 async fn selector_returns_valid_ids() {
571 let mut selector = StreamSelector::default();
572 let id_0 = selector.push(futures::stream::repeat(0)).id().clone();
573 let id_1 = selector.push(futures::stream::repeat(1)).id().clone();
574 assert!(selector.contains(&id_0));
575 assert!(selector.contains(&id_1));
576 assert_eq!(selector.next().await.unwrap(), 0);
577 assert_eq!(selector.next().await.unwrap(), 1);
578 assert_eq!(selector.next().await.unwrap(), 0);
579 assert_eq!(selector.next().await.unwrap(), 1);
580 selector.remove(&id_0);
581 assert_eq!(selector.next().await.unwrap(), 1);
582 assert_eq!(selector.next().await.unwrap(), 1);
583 }
584
585 #[tokio::test]
586 async fn selector_handles_strategy_panic() {
587 struct MyTask(usize);
588
589 impl Task for MyTask {
590 type Cont = usize;
591 type Break = usize;
592 type Output = usize;
593
594 fn poll_progress(
595 self: Pin<&mut Self>,
596 _: &mut (),
597 _: &mut Context<'_>,
598 ) -> Poll<ControlFlow<Self::Break, Self::Cont>> {
599 match self.0 {
600 1 => panic!("poll panic"),
601 2 => Poll::Ready(ControlFlow::Continue(2)),
602 n => Poll::Ready(ControlFlow::Break(n)),
603 }
604 }
605
606 fn transform_cont(
607 _: BorrowedMut<'_, Self>,
608 _: &mut (),
609 _: Self::Cont,
610 ) -> Option<Self::Output> {
611 panic!("cont panic")
612 }
613
614 fn transform_break(
615 _: Removed<Self>,
616 _: &mut (),
617 value: Self::Break,
618 ) -> Option<Self::Output> {
619 if value == 3 {
620 panic!("break panic")
621 } else {
622 Some(value)
623 }
624 }
625 }
626
627 let mut selector = (0..=4).map(MyTask).collect::<Selector<_, ()>>();
628 assert_eq!(selector.len(), 5);
629
630 assert_eq!(selector.next().await.unwrap(), 0);
631 assert_eq!(selector.len(), 4);
632
633 let err = AssertUnwindSafe(selector.next())
634 .catch_unwind()
635 .await
636 .unwrap_err();
637 assert_eq!(*err.downcast_ref::<&'static str>().unwrap(), "poll panic",);
638 assert_eq!(selector.len(), 3);
639
640 let err = AssertUnwindSafe(selector.next())
641 .catch_unwind()
642 .await
643 .unwrap_err();
644 assert_eq!(*err.downcast_ref::<&'static str>().unwrap(), "cont panic",);
645 assert_eq!(selector.len(), 2);
646
647 let err = AssertUnwindSafe(selector.next())
648 .catch_unwind()
649 .await
650 .unwrap_err();
651 assert_eq!(*err.downcast_ref::<&'static str>().unwrap(), "break panic",);
652 assert_eq!(selector.len(), 1);
653
654 assert_eq!(selector.next().await.unwrap(), 4);
655 assert_eq!(selector.len(), 0);
656 }
657
658 #[tokio::test]
659 async fn selector_handles_drop_panic() {
660 struct Task(usize);
661
662 impl Future for Task {
663 type Output = usize;
664
665 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
666 Poll::Ready(self.0)
667 }
668 }
669
670 impl Drop for Task {
671 fn drop(&mut self) {
672 if self.0 < 2 {
673 panic!();
674 }
675 }
676 }
677
678 let mut selector = (0..3).map(Task).collect::<FutureSelector<_>>();
679 let ids = selector
680 .iter()
681 .map(|task| task.id().clone())
682 .collect::<Vec<_>>();
683
684 AssertUnwindSafe(selector.next())
685 .catch_unwind()
686 .await
687 .unwrap_err();
688 assert_eq!(selector.len(), 2);
689 assert_eq!(Arc::strong_count(ids[0].get()), 1);
690
691 let selector = AssertUnwindSafe(selector);
692 std::panic::catch_unwind(|| drop(selector)).unwrap_err();
693
694 for id in ids {
695 assert_eq!(Arc::strong_count(id.get()), 1);
696 }
697 }
698}