1use std::{
4 fmt,
5 marker::PhantomData,
6 ops::{ControlFlow, Not},
7 pin::Pin,
8 sync::Arc,
9 task::{Context, Poll},
10};
11
12use futures::{Stream, StreamExt};
13
14use crate::{
15 list::{
16 IntrusiveList,
17 cursor::{Cursor, CursorMut},
18 },
19 mpsc,
20 pollable::{PollDirect, PollProxy, Pollable},
21 selector::{
22 ext::{WithExt, WithExtAndId, WithId},
23 iter::{ExtractIf, IntoIter, Iter, IterMut},
24 },
25 task::Task,
26};
27
28pub use borrowed::{Borrowed, BorrowedMut};
29pub use id::Id;
30pub use removed::Removed;
31
32mod borrowed;
33pub mod ext;
34mod id;
35pub mod iter;
36mod removed;
37
38pub struct Selector<T, P = PollDirect> {
83 ready_rx: mpsc::Receiver<Task<T>>,
85 list: IntrusiveList<Task<T>>,
87 _proxy: PhantomData<fn() -> P>,
88}
89
90impl<T, P> Selector<T, P> {
91 pub fn push(&mut self, task: T) {
95 let task = self
96 .list
97 .insert(Task::empty(self.ready_rx.weak_sender()), task);
98 self.ready_rx.send(task);
99 }
100
101 pub fn push_with_id(&mut self, task: T) -> Id<T> {
105 let task = self
106 .list
107 .insert(Task::empty(self.ready_rx.weak_sender()), task);
108 let id = Id(Arc::downgrade(&task));
109 self.ready_rx.send(task);
110 id
111 }
112
113 pub fn is_empty(&self) -> bool {
117 self.list.is_empty()
118 }
119
120 pub fn len(&self) -> usize {
124 self.list.len()
125 }
126
127 pub fn wake_all(&self) {
135 self.iter().for_each(|borrowed| borrowed.wake());
136 }
137
138 pub fn iter(&self) -> Iter<'_, T> {
142 Iter {
143 cursor: Cursor::new(&self.list),
144 queue: &self.ready_rx,
145 }
146 }
147
148 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
154 IterMut {
155 cursor: CursorMut::new(&mut self.list),
156 queue: &self.ready_rx,
157 }
158 }
159
160 #[must_use = "ExtractIf does not remove any elements unless consumed"]
169 pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, T, F>
170 where
171 F: FnMut(Pin<&mut T>) -> bool,
172 {
173 ExtractIf {
174 cursor: CursorMut::new(&mut self.list),
175 pred,
176 }
177 }
178
179 pub fn get(&self, id: &Id<T>) -> Option<Borrowed<'_, T>> {
186 let task = id.0.upgrade()?;
187 if self.ready_rx.is_parent(task.ready_tx()).not() {
188 return None;
189 }
190 let node = unsafe {
191 self.list.get(&task)
194 }?;
195 Some(Borrowed {
196 node,
197 queue: &self.ready_rx,
198 })
199 }
200
201 pub fn get_mut(&mut self, id: &Id<T>) -> Option<BorrowedMut<'_, T>> {
210 let task = id.0.upgrade()?;
211 if self.ready_rx.is_parent(task.ready_tx()).not() {
212 return None;
213 }
214 let node = unsafe {
215 self.list.get_mut(&task)
218 }?;
219 Some(BorrowedMut {
220 node,
221 queue: &self.ready_rx,
222 })
223 }
224
225 pub fn remove(&mut self, id: &Id<T>) -> Option<Removed<T>> {
234 let task = id.0.upgrade()?;
235 if self.ready_rx.is_parent(task.ready_tx()).not() {
236 return None;
237 }
238 let removed = unsafe {
239 self.list.remove(&task)?
242 };
243 Some(Removed(removed))
244 }
245
246 pub fn with_ext<'s, 'e, 'emut, E, EMut>(
250 &'s mut self,
251 ext: &'e E,
252 ext_mut: &'emut mut EMut,
253 ) -> WithExt<'s, 'e, 'emut, T, P, E, EMut>
254 where
255 P: PollProxy<'e, T, E, EMut>,
256 E: ?Sized,
257 EMut: ?Sized,
258 {
259 WithExt {
260 selector: self,
261 ext,
262 ext_mut,
263 }
264 }
265
266 pub fn with_id(&mut self) -> WithId<'_, T, P>
268 where
269 P: PollProxy<'static, T, (), ()>,
270 {
271 WithId { selector: self }
272 }
273
274 pub fn with_ext_and_id<'s, 'e, 'emut, E, EMut>(
279 &'s mut self,
280 ext: &'e E,
281 ext_mut: &'emut mut EMut,
282 ) -> WithExtAndId<'s, 'e, 'emut, T, P, E, EMut>
283 where
284 P: PollProxy<'e, T, E, EMut>,
285 E: ?Sized,
286 EMut: ?Sized,
287 {
288 WithExtAndId {
289 selector: self,
290 ext,
291 ext_mut,
292 }
293 }
294
295 #[allow(clippy::type_complexity)]
302 fn poll_next_inner<'a, E, EMut, F, I>(
303 &mut self,
304 ext: &'a E,
305 ext_mut: &mut EMut,
306 extra: F,
307 cx: &mut Context<'_>,
308 ) -> Poll<Option<(P::Progress, I)>>
309 where
310 P: PollProxy<'a, T, E, EMut>,
311 E: ?Sized,
312 EMut: ?Sized,
313 F: FnOnce(&Arc<Task<T>>) -> I,
314 {
315 let marker = self.ready_rx.register(cx.waker());
316 if marker.is_null() {
317 return if self.list.is_empty() {
318 Poll::Ready(None)
319 } else {
320 Poll::Pending
321 };
322 }
323
324 let mut polled_all_queue = false;
325 while polled_all_queue.not() {
326 let task = match self.ready_rx.recv() {
327 Some(task) => {
328 polled_all_queue = std::ptr::eq(task.as_ref(), marker);
329 task
330 }
331 None if self.list.is_empty() => return Poll::Ready(None),
332 None => return Poll::Pending,
333 };
334
335 let mut guard = {
336 let guard = unsafe {
337 self.list.access(&task)
340 };
341 match guard {
342 Some(guard) => guard,
343 None => continue,
344 }
345 };
346 let waker = task.borrow_waker();
347 let mut cx = Context::from_waker(&waker);
348
349 let result = P::poll_progress(guard.get(), ext, ext_mut, &mut cx);
351
352 match result {
353 Poll::Ready(ControlFlow::Continue(item)) => {
354 guard.forget();
355 let extra = extra(&task);
356 self.ready_rx.send(task);
357 return Poll::Ready(Some((item, extra)));
358 }
359 Poll::Ready(ControlFlow::Break(Some(item))) => {
360 let extra = extra(&task);
361 return Poll::Ready(Some((item, extra)));
362 }
363 Poll::Ready(ControlFlow::Break(None)) => {}
364 Poll::Pending => guard.forget(),
365 }
366 }
367
368 if self.list.is_empty() {
369 Poll::Ready(None)
370 } else {
371 Poll::Pending
372 }
373 }
374}
375
376impl<T, P> Stream for Selector<T, P>
377where
378 P: PollProxy<'static, T, (), ()>,
379{
380 type Item = P::Progress;
381
382 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
383 let this = unsafe {
384 self.get_unchecked_mut()
386 };
387 this.poll_next_inner(&(), &mut (), |_| (), cx)
388 .map(|opt| opt.map(|(item, ())| item))
389 }
390}
391
392impl<'a, T, P, E, EMut> Pollable<'a, E, EMut> for Selector<T, P>
393where
394 P: PollProxy<'a, T, E, EMut>,
395 E: ?Sized,
396 EMut: ?Sized,
397{
398 type Progress = P::Progress;
399
400 fn poll_progress(
401 self: Pin<&mut Self>,
402 ext: &'a E,
403 ext_mut: &mut EMut,
404 cx: &mut Context<'_>,
405 ) -> Poll<ControlFlow<Option<Self::Progress>, Self::Progress>> {
406 self.get_mut()
407 .with_ext(ext, ext_mut)
408 .poll_next_unpin(cx)
409 .map(|opt| opt.map_or(ControlFlow::Break(None), ControlFlow::Continue))
410 }
411}
412
413impl<T, P> Default for Selector<T, P> {
414 fn default() -> Self {
415 Self {
416 ready_rx: mpsc::Receiver::new(Task::empty),
417 list: Default::default(),
418 _proxy: Default::default(),
419 }
420 }
421}
422
423impl<T, P> fmt::Debug for Selector<T, P> {
424 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
425 f.debug_struct("Selector")
426 .field("len", &self.len())
427 .finish()
428 }
429}
430
431impl<T, P> Extend<T> for Selector<T, P> {
432 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
433 for pollable in iter {
434 self.push(pollable);
435 }
436 }
437}
438
439impl<T, P> FromIterator<T> for Selector<T, P> {
440 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
441 let mut this = Self::default();
442 this.extend(iter);
443 this
444 }
445}
446
447impl<T, P> IntoIterator for Selector<T, P> {
448 type IntoIter = IntoIter<T>;
449 type Item = Removed<T>;
450
451 fn into_iter(self) -> Self::IntoIter {
452 IntoIter(self.list)
453 }
454}
455
456#[cfg(test)]
457mod test {
458 use std::{
459 ops::Not,
460 panic::{AssertUnwindSafe, catch_unwind},
461 pin::Pin,
462 sync::Arc,
463 task::{Context, Poll, Waker},
464 };
465
466 use futures::{FutureExt, StreamExt, channel::oneshot, task::AtomicWaker};
467 use rstest::rstest;
468
469 use crate::{pollable::PollFuture, selector::Selector};
470
471 #[tokio::test]
472 async fn basic() {
473 let (tx, rx) = oneshot::channel::<()>();
474 let mut selector = Selector::<_, PollFuture>::default();
475 selector.push(rx);
476 assert!(selector.next().now_or_never().is_none());
477 assert_eq!(selector.len(), 1);
478 tx.send(()).unwrap();
479 assert!(selector.next().await.is_some());
480 assert_eq!(selector.len(), 0);
481 }
482
483 #[rstest]
486 #[tokio::test]
487 async fn task_yield_is_respected(#[values(1, 4, 8)] futures: usize) {
488 struct Fut {
489 polled: bool,
490 }
491
492 impl Future for Fut {
493 type Output = ();
494
495 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
496 let this = self.get_mut();
497 if this.polled.not() {
498 this.polled = true;
499 cx.waker().wake_by_ref();
500 Poll::Pending
501 } else {
502 Poll::Ready(())
503 }
504 }
505 }
506
507 let mut selector = Selector::<_, PollFuture>::default();
508 for _ in 0..futures {
509 selector.push(Fut { polled: false });
510 }
511
512 assert!(
513 selector
514 .poll_next_unpin(&mut Context::from_waker(Waker::noop()))
515 .is_pending()
516 );
517 for fut in selector.iter() {
518 assert!(fut.polled);
519 }
520
521 for _ in 0..futures {
522 assert_eq!(
523 selector.poll_next_unpin(&mut Context::from_waker(Waker::noop())),
524 Poll::Ready(Some(())),
525 );
526 }
527 }
528
529 #[test]
530 fn stale_wakeups_on_removed_tasks_still_report_empty_selector() {
531 struct StoreWaker(Arc<AtomicWaker>);
532
533 impl Future for StoreWaker {
534 type Output = usize;
535
536 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
537 self.0.register(cx.waker());
538 Poll::Pending
539 }
540 }
541
542 let slot = Arc::new(AtomicWaker::new());
543 let mut selector = Selector::<_, PollFuture>::default();
544 let id = selector.push_with_id(StoreWaker(slot.clone()).boxed());
545 let mut cx = Context::from_waker(Waker::noop());
546
547 assert!(selector.poll_next_unpin(&mut cx).is_pending());
548 let waker = slot.take().unwrap();
549 let _ = selector.remove(&id).unwrap();
550 assert!(selector.is_empty());
551
552 for _ in 0..3 {
553 waker.wake_by_ref();
554 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
555 }
556
557 selector.push(std::future::ready(7).boxed());
558 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(7)));
559 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
560 }
561
562 #[test]
563 fn panicking_task_is_removed_and_selector_remains_valid() {
564 struct PanicOnPoll {
565 _shared: Arc<()>,
566 }
567
568 impl Future for PanicOnPoll {
569 type Output = usize;
570
571 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
572 panic!("boom");
573 }
574 }
575
576 let drops = Arc::new(());
577 let drops_weak = Arc::downgrade(&drops);
578 let mut selector = Selector::<_, PollFuture>::default();
579 selector.push(PanicOnPoll { _shared: drops }.boxed());
580
581 let mut cx = Context::from_waker(Waker::noop());
582 let result = catch_unwind(AssertUnwindSafe(|| selector.poll_next_unpin(&mut cx)));
583
584 assert!(result.is_err());
585 assert!(selector.is_empty());
586 assert_eq!(selector.len(), 0);
587 assert!(drops_weak.upgrade().is_none());
588
589 selector.push(std::future::ready(11).boxed());
590 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(11)));
591 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
592 }
593}