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::{PollStrategy, PollWith},
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<S: PollStrategy> {
84 ready_rx: mpsc::Receiver<Task<S::Pollable>>,
86 list: IntrusiveList<Task<S::Pollable>>,
88 _phantom: PhantomData<fn() -> S>,
90}
91
92impl<S: PollStrategy> Selector<S> {
93 pub fn push(&mut self, pollable: S::Pollable) {
97 let node = self
98 .list
99 .insert(Task::empty(self.ready_rx.weak_sender()), pollable);
100 self.ready_rx.send(node);
101 }
102
103 pub fn push_with_id(&mut self, pollable: S::Pollable) -> Id<S::Pollable> {
107 let node = self
108 .list
109 .insert(Task::empty(self.ready_rx.weak_sender()), pollable);
110 let id = Id(Arc::downgrade(&node));
111 self.ready_rx.send(node);
112 id
113 }
114
115 pub fn is_empty(&self) -> bool {
119 self.list.is_empty()
120 }
121
122 pub fn len(&self) -> usize {
126 self.list.len()
127 }
128
129 pub fn wake_all(&self) {
137 self.iter().for_each(|borrowed| borrowed.wake());
138 }
139
140 pub fn iter(&self) -> Iter<'_, S::Pollable> {
144 Iter {
145 cursor: Cursor::new(&self.list),
146 queue: &self.ready_rx,
147 }
148 }
149
150 pub fn iter_mut(&mut self) -> IterMut<'_, S::Pollable> {
156 IterMut {
157 cursor: CursorMut::new(&mut self.list),
158 queue: &self.ready_rx,
159 }
160 }
161
162 #[must_use = "ExtractIf does not remove any elements unless consumed"]
171 pub fn extract_if<F>(&mut self, pred: F) -> ExtractIf<'_, S::Pollable, F>
172 where
173 F: FnMut(Pin<&mut S::Pollable>) -> bool,
174 {
175 ExtractIf {
176 cursor: CursorMut::new(&mut self.list),
177 pred,
178 }
179 }
180
181 pub fn get(&self, id: &Id<S::Pollable>) -> Option<Borrowed<'_, S::Pollable>> {
188 let task = id.0.upgrade()?;
189 if self.ready_rx.is_parent(task.ready_tx()).not() {
190 return None;
191 }
192 let node = unsafe {
193 self.list.get(&task)
196 }?;
197 Some(Borrowed {
198 node,
199 queue: &self.ready_rx,
200 })
201 }
202
203 pub fn get_mut(&mut self, id: &Id<S::Pollable>) -> Option<BorrowedMut<'_, S::Pollable>> {
212 let task = id.0.upgrade()?;
213 if self.ready_rx.is_parent(task.ready_tx()).not() {
214 return None;
215 }
216 let node = unsafe {
217 self.list.get_mut(&task)
220 }?;
221 Some(BorrowedMut {
222 node,
223 queue: &self.ready_rx,
224 })
225 }
226
227 pub fn remove(&mut self, id: &Id<S::Pollable>) -> Option<Removed<S::Pollable>> {
236 let task = id.0.upgrade()?;
237 if self.ready_rx.is_parent(task.ready_tx()).not() {
238 return None;
239 }
240 let removed = unsafe {
241 self.list.remove(&task)?
244 };
245 Some(Removed(removed))
246 }
247
248 pub fn with_ext<'s, 'e, 'emut, E: ?Sized, EMut: ?Sized>(
252 &'s mut self,
253 ext: &'e E,
254 ext_mut: &'emut mut EMut,
255 ) -> WithExt<'s, 'e, 'emut, S, E, EMut> {
256 WithExt {
257 selector: self,
258 ext,
259 ext_mut,
260 }
261 }
262
263 pub fn with_id(&mut self) -> WithId<'_, S> {
265 WithId { selector: self }
266 }
267
268 pub fn with_ext_and_id<'s, 'e, 'emut, E: ?Sized, EMut: ?Sized>(
273 &'s mut self,
274 ext: &'e E,
275 ext_mut: &'emut mut EMut,
276 ) -> WithExtAndId<'s, 'e, 'emut, S, E, EMut> {
277 WithExtAndId {
278 selector: self,
279 ext,
280 ext_mut,
281 }
282 }
283
284 #[allow(clippy::type_complexity)]
291 fn poll_next_inner<'a, E, EMut, F, T>(
292 &mut self,
293 ext: &'a E,
294 ext_mut: &mut EMut,
295 extra: F,
296 cx: &mut Context<'_>,
297 ) -> Poll<Option<(<S as PollWith<'a, E, EMut>>::Progress, T)>>
298 where
299 S: PollWith<'a, E, EMut>,
300 E: ?Sized,
301 EMut: ?Sized,
302 F: FnOnce(&Arc<Task<S::Pollable>>) -> T,
303 {
304 let marker = self.ready_rx.register(cx.waker());
305 if marker.is_null() {
306 return if self.list.is_empty() {
307 Poll::Ready(None)
308 } else {
309 Poll::Pending
310 };
311 }
312
313 let mut polled_all_queue = false;
314 while polled_all_queue.not() {
315 let task = match self.ready_rx.recv() {
316 Some(task) => {
317 polled_all_queue = std::ptr::eq(task.as_ref(), marker);
318 task
319 }
320 None if self.list.is_empty() => return Poll::Ready(None),
321 None => return Poll::Pending,
322 };
323
324 let mut guard = {
325 let guard = unsafe {
326 self.list.access(&task)
329 };
330 match guard {
331 Some(guard) => guard,
332 None => continue,
333 }
334 };
335 let waker = task.borrow_waker();
336 let mut cx = Context::from_waker(&waker);
337
338 let result = S::poll_progress(guard.get(), ext, ext_mut, &mut cx);
340
341 match result {
342 Poll::Ready(ControlFlow::Continue(item)) => {
343 guard.forget();
344 let extra = extra(&task);
345 self.ready_rx.send(task);
346 return Poll::Ready(Some((item, extra)));
347 }
348 Poll::Ready(ControlFlow::Break(Some(item))) => {
349 let extra = extra(&task);
350 return Poll::Ready(Some((item, extra)));
351 }
352 Poll::Ready(ControlFlow::Break(None)) => {}
353 Poll::Pending => guard.forget(),
354 }
355 }
356
357 if self.list.is_empty() {
358 Poll::Ready(None)
359 } else {
360 Poll::Pending
361 }
362 }
363}
364
365impl<S: PollWith<'static, (), ()>> Stream for Selector<S> {
366 type Item = S::Progress;
367
368 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
369 let this = unsafe {
370 self.get_unchecked_mut()
372 };
373 this.poll_next_inner(&(), &mut (), |_| (), cx)
374 .map(|opt| opt.map(|(item, ())| item))
375 }
376}
377
378impl<S: PollStrategy> Default for Selector<S> {
379 fn default() -> Self {
380 Self {
381 ready_rx: mpsc::Receiver::new(Task::empty),
382 list: Default::default(),
383 _phantom: Default::default(),
384 }
385 }
386}
387
388impl<S: PollStrategy> fmt::Debug for Selector<S> {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390 f.debug_struct("Selector")
391 .field("len", &self.len())
392 .finish()
393 }
394}
395
396impl<S: PollStrategy> Extend<S::Pollable> for Selector<S> {
397 fn extend<T: IntoIterator<Item = S::Pollable>>(&mut self, iter: T) {
398 for pollable in iter {
399 self.push(pollable);
400 }
401 }
402}
403
404impl<S: PollStrategy> FromIterator<S::Pollable> for Selector<S> {
405 fn from_iter<T: IntoIterator<Item = S::Pollable>>(iter: T) -> Self {
406 let mut this = Self::default();
407 this.extend(iter);
408 this
409 }
410}
411
412impl<S: PollStrategy> IntoIterator for Selector<S> {
413 type IntoIter = IntoIter<S::Pollable>;
414 type Item = Removed<S::Pollable>;
415
416 fn into_iter(self) -> Self::IntoIter {
417 IntoIter(self.list)
418 }
419}
420
421#[cfg(test)]
422mod test {
423 use std::{
424 ops::Not,
425 panic::{AssertUnwindSafe, catch_unwind},
426 pin::Pin,
427 sync::Arc,
428 task::{Context, Poll, Waker},
429 };
430
431 use futures::{FutureExt, StreamExt, channel::oneshot, task::AtomicWaker};
432 use rstest::rstest;
433
434 use crate::{pollable::PollAsFuture, selector::Selector};
435
436 #[tokio::test]
437 async fn basic() {
438 let (tx, rx) = oneshot::channel::<()>();
439 let mut selector = Selector::<PollAsFuture<_>>::default();
440 selector.push(rx);
441 assert!(selector.next().now_or_never().is_none());
442 assert_eq!(selector.len(), 1);
443 tx.send(()).unwrap();
444 assert!(selector.next().await.is_some());
445 assert_eq!(selector.len(), 0);
446 }
447
448 #[rstest]
451 #[tokio::test]
452 async fn task_yield_is_respected(#[values(1, 4, 8)] futures: usize) {
453 struct Fut {
454 polled: bool,
455 }
456
457 impl Future for Fut {
458 type Output = ();
459
460 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
461 let this = self.get_mut();
462 if this.polled.not() {
463 this.polled = true;
464 cx.waker().wake_by_ref();
465 Poll::Pending
466 } else {
467 Poll::Ready(())
468 }
469 }
470 }
471
472 let mut selector = Selector::<PollAsFuture<_>>::default();
473 for _ in 0..futures {
474 selector.push(Fut { polled: false });
475 }
476
477 assert!(
478 selector
479 .poll_next_unpin(&mut Context::from_waker(Waker::noop()))
480 .is_pending()
481 );
482 for fut in selector.iter() {
483 assert!(fut.polled);
484 }
485
486 for _ in 0..futures {
487 assert_eq!(
488 selector.poll_next_unpin(&mut Context::from_waker(Waker::noop())),
489 Poll::Ready(Some(())),
490 );
491 }
492 }
493
494 #[test]
495 fn stale_wakeups_on_removed_tasks_still_report_empty_selector() {
496 struct StoreWaker(Arc<AtomicWaker>);
497
498 impl Future for StoreWaker {
499 type Output = usize;
500
501 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
502 self.0.register(cx.waker());
503 Poll::Pending
504 }
505 }
506
507 let slot = Arc::new(AtomicWaker::new());
508 let mut selector = Selector::<PollAsFuture<_>>::default();
509 let id = selector.push_with_id(StoreWaker(slot.clone()).boxed());
510 let mut cx = Context::from_waker(Waker::noop());
511
512 assert!(selector.poll_next_unpin(&mut cx).is_pending());
513 let waker = slot.take().unwrap();
514 let _ = selector.remove(&id).unwrap();
515 assert!(selector.is_empty());
516
517 for _ in 0..3 {
518 waker.wake_by_ref();
519 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
520 }
521
522 selector.push(std::future::ready(7).boxed());
523 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(7)));
524 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
525 }
526
527 #[test]
528 fn panicking_task_is_removed_and_selector_remains_valid() {
529 struct PanicOnPoll {
530 _shared: Arc<()>,
531 }
532
533 impl Future for PanicOnPoll {
534 type Output = usize;
535
536 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
537 panic!("boom");
538 }
539 }
540
541 let drops = Arc::new(());
542 let drops_weak = Arc::downgrade(&drops);
543 let mut selector = Selector::<PollAsFuture<_>>::default();
544 selector.push(PanicOnPoll { _shared: drops }.boxed());
545
546 let mut cx = Context::from_waker(Waker::noop());
547 let result = catch_unwind(AssertUnwindSafe(|| selector.poll_next_unpin(&mut cx)));
548
549 assert!(result.is_err());
550 assert!(selector.is_empty());
551 assert_eq!(selector.len(), 0);
552 assert!(drops_weak.upgrade().is_none());
553
554 selector.push(std::future::ready(11).boxed());
555 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(Some(11)));
556 assert_eq!(selector.poll_next_unpin(&mut cx), Poll::Ready(None));
557 }
558}