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;
13
14use crate::{
15 list::{
16 IntrusiveList,
17 cursor::{Cursor, CursorMut},
18 },
19 mpsc,
20 pollable::{PollDirect, PollProxy},
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<T, P> Default for Selector<T, P> {
393 fn default() -> Self {
394 Self {
395 ready_rx: mpsc::Receiver::new(Task::empty),
396 list: Default::default(),
397 _proxy: Default::default(),
398 }
399 }
400}
401
402impl<T, P> fmt::Debug for Selector<T, P> {
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 f.debug_struct("Selector")
405 .field("len", &self.len())
406 .finish()
407 }
408}
409
410impl<T, P> Extend<T> for Selector<T, P> {
411 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
412 for pollable in iter {
413 self.push(pollable);
414 }
415 }
416}
417
418impl<T, S> FromIterator<T> for Selector<T, S> {
419 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
420 let mut this = Self::default();
421 this.extend(iter);
422 this
423 }
424}
425
426impl<T, S> IntoIterator for Selector<T, S> {
427 type IntoIter = IntoIter<T>;
428 type Item = Removed<T>;
429
430 fn into_iter(self) -> Self::IntoIter {
431 IntoIter(self.list)
432 }
433}
434
435#[cfg(test)]
436mod test {
437 use std::{
438 ops::Not,
439 panic::{AssertUnwindSafe, catch_unwind},
440 pin::Pin,
441 sync::Arc,
442 task::{Context, Poll, Waker},
443 };
444
445 use futures::{FutureExt, StreamExt, channel::oneshot, task::AtomicWaker};
446 use rstest::rstest;
447
448 use crate::{pollable::PollFuture, selector::Selector};
449
450 #[tokio::test]
451 async fn basic() {
452 let (tx, rx) = oneshot::channel::<()>();
453 let mut selector = Selector::<_, PollFuture>::default();
454 selector.push(rx);
455 assert!(selector.next().now_or_never().is_none());
456 assert_eq!(selector.len(), 1);
457 tx.send(()).unwrap();
458 assert!(selector.next().await.is_some());
459 assert_eq!(selector.len(), 0);
460 }
461
462 #[rstest]
465 #[tokio::test]
466 async fn task_yield_is_respected(#[values(1, 4, 8)] futures: usize) {
467 struct Fut {
468 polled: bool,
469 }
470
471 impl Future for Fut {
472 type Output = ();
473
474 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
475 let this = self.get_mut();
476 if this.polled.not() {
477 this.polled = true;
478 cx.waker().wake_by_ref();
479 Poll::Pending
480 } else {
481 Poll::Ready(())
482 }
483 }
484 }
485
486 let mut selector = Selector::<_, PollFuture>::default();
487 for _ in 0..futures {
488 selector.push(Fut { polled: false });
489 }
490
491 assert!(
492 selector
493 .poll_next_unpin(&mut Context::from_waker(Waker::noop()))
494 .is_pending()
495 );
496 for fut in selector.iter() {
497 assert!(fut.polled);
498 }
499
500 for _ in 0..futures {
501 assert_eq!(
502 selector.poll_next_unpin(&mut Context::from_waker(Waker::noop())),
503 Poll::Ready(Some(())),
504 );
505 }
506 }
507
508 #[test]
509 fn stale_wakeups_on_removed_tasks_still_report_empty_selector() {
510 struct StoreWaker(Arc<AtomicWaker>);
511
512 impl Future for StoreWaker {
513 type Output = usize;
514
515 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
516 self.0.register(cx.waker());
517 Poll::Pending
518 }
519 }
520
521 let slot = Arc::new(AtomicWaker::new());
522 let mut selector = Selector::<_, PollFuture>::default();
523 let id = selector.push_with_id(StoreWaker(slot.clone()).boxed());
524 let mut cx = Context::from_waker(Waker::noop());
525
526 assert!(selector.poll_next_unpin(&mut cx).is_pending());
527 let waker = slot.take().unwrap();
528 let _ = selector.remove(&id).unwrap();
529 assert!(selector.is_empty());
530
531 for _ in 0..3 {
532 waker.wake_by_ref();
533 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
534 }
535
536 selector.push(std::future::ready(7).boxed());
537 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(7)));
538 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
539 }
540
541 #[test]
542 fn panicking_task_is_removed_and_selector_remains_valid() {
543 struct PanicOnPoll {
544 _shared: Arc<()>,
545 }
546
547 impl Future for PanicOnPoll {
548 type Output = usize;
549
550 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
551 panic!("boom");
552 }
553 }
554
555 let drops = Arc::new(());
556 let drops_weak = Arc::downgrade(&drops);
557 let mut selector = Selector::<_, PollFuture>::default();
558 selector.push(PanicOnPoll { _shared: drops }.boxed());
559
560 let mut cx = Context::from_waker(Waker::noop());
561 let result = catch_unwind(AssertUnwindSafe(|| selector.poll_next_unpin(&mut cx)));
562
563 assert!(result.is_err());
564 assert!(selector.is_empty());
565 assert_eq!(selector.len(), 0);
566 assert!(drops_weak.upgrade().is_none());
567
568 selector.push(std::future::ready(11).boxed());
569 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(11)));
570 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
571 }
572}