Skip to main content

async_selector/selector/
iter.rs

1//! Types for iterating over tasks stored in a [`Selector`](crate::selector::Selector).
2
3use std::pin::Pin;
4
5use crate::{
6    list::{
7        IntrusiveList,
8        cursor::{Cursor, CursorMut},
9    },
10    mpsc,
11    selector::{
12        Removed,
13        borrowed::{Borrowed, BorrowedMut},
14    },
15    task::Task,
16};
17
18/// Iterator that visits tasks stored in a [`Selector`](crate::selector::Selector).
19///
20/// Tasks are visited in the insertion order.
21pub struct Iter<'a, P> {
22    pub(super) cursor: Cursor<'a, Task<P>>,
23    pub(super) queue: &'a mpsc::Receiver<Task<P>>,
24}
25
26impl<'a, P> Iterator for Iter<'a, P> {
27    type Item = Borrowed<'a, P>;
28
29    fn next(&mut self) -> Option<Self::Item> {
30        Some(Borrowed {
31            node: self.cursor.pop_front()?,
32            queue: self.queue,
33        })
34    }
35
36    fn size_hint(&self) -> (usize, Option<usize>) {
37        let len = self.cursor.len();
38        (len, Some(len))
39    }
40}
41
42impl<P> ExactSizeIterator for Iter<'_, P> {
43    fn len(&self) -> usize {
44        self.cursor.len()
45    }
46}
47
48impl<P> DoubleEndedIterator for Iter<'_, P> {
49    fn next_back(&mut self) -> Option<Self::Item> {
50        Some(Borrowed {
51            node: self.cursor.pop_back()?,
52            queue: self.queue,
53        })
54    }
55}
56
57/// Iterator that allows for modifying tasks stored in a [`Selector`](crate::selector::Selector).
58///
59/// Tasks are visited in the insertion order.
60///
61/// **Important:** before modifying tasks stored in the selector, see the wakeups [section](crate::selector::Selector#wakeups).
62pub struct IterMut<'a, P> {
63    pub(super) cursor: CursorMut<'a, Task<P>>,
64    pub(super) queue: &'a mpsc::Receiver<Task<P>>,
65}
66
67impl<'a, P> Iterator for IterMut<'a, P> {
68    type Item = BorrowedMut<'a, P>;
69
70    fn next(&mut self) -> Option<Self::Item> {
71        Some(BorrowedMut {
72            node: self.cursor.pop_front()?,
73            queue: self.queue,
74        })
75    }
76
77    fn size_hint(&self) -> (usize, Option<usize>) {
78        let len = self.cursor.len();
79        (len, Some(len))
80    }
81}
82
83impl<P> ExactSizeIterator for IterMut<'_, P> {
84    fn len(&self) -> usize {
85        self.cursor.len()
86    }
87}
88
89impl<P> DoubleEndedIterator for IterMut<'_, P> {
90    fn next_back(&mut self) -> Option<Self::Item> {
91        Some(BorrowedMut {
92            node: self.cursor.pop_back()?,
93            queue: self.queue,
94        })
95    }
96}
97
98/// Iterator that returns tasks stored previously in a [`Selector`](crate::selector::Selector).
99///
100/// If the iterator is not exhausted, e.g. because it is dropped without iterating or the iteration short-circuits,
101/// then the remaining tasks are dropped.
102pub struct IntoIter<P>(pub(super) IntrusiveList<Task<P>>);
103
104impl<P> Iterator for IntoIter<P> {
105    type Item = Removed<P>;
106
107    fn next(&mut self) -> Option<Self::Item> {
108        CursorMut::new(&mut self.0).remove_front().map(Removed)
109    }
110
111    fn size_hint(&self) -> (usize, Option<usize>) {
112        let len = self.0.len();
113        (len, Some(len))
114    }
115}
116
117impl<P> ExactSizeIterator for IntoIter<P> {
118    fn len(&self) -> usize {
119        self.0.len()
120    }
121}
122
123impl<P> DoubleEndedIterator for IntoIter<P> {
124    fn next_back(&mut self) -> Option<Self::Item> {
125        CursorMut::new(&mut self.0).remove_back().map(Removed)
126    }
127}
128
129/// Iterator which uses a closure to determine if a task should be removed from a [`Selector`](crate::selector::Selector).
130///
131/// If the closure returns true, the task is removed from the selector and yielded.
132///
133/// If the iterator is not exhausted, e.g. because it is dropped without iterating or the iteration short-circuits,
134/// then the remaining tasks will be retained.
135///
136/// **Important:** before removing tasks from the selector, see the removal [section](crate::selector::Selector#removal).
137pub struct ExtractIf<'a, P, F>
138where
139    F: FnMut(Pin<&mut P>) -> bool,
140{
141    pub(super) cursor: CursorMut<'a, Task<P>>,
142    pub(super) pred: F,
143}
144
145impl<'a, P, F> Iterator for ExtractIf<'a, P, F>
146where
147    F: FnMut(Pin<&mut P>) -> bool,
148{
149    type Item = Removed<P>;
150
151    fn next(&mut self) -> Option<Self::Item> {
152        loop {
153            let mut front = self.cursor.peek_front()?;
154            if (self.pred)(front.get_protected_mut()) {
155                return self.cursor.remove_front().map(Removed);
156            } else {
157                self.cursor.pop_front();
158            }
159        }
160    }
161
162    fn size_hint(&self) -> (usize, Option<usize>) {
163        let len = self.cursor.len();
164        (0, Some(len))
165    }
166}
167
168impl<'a, P, F> DoubleEndedIterator for ExtractIf<'a, P, F>
169where
170    F: FnMut(Pin<&mut P>) -> bool,
171{
172    fn next_back(&mut self) -> Option<Self::Item> {
173        loop {
174            let mut back = self.cursor.peek_back()?;
175            if (self.pred)(back.get_protected_mut()) {
176                return self.cursor.remove_back().map(Removed);
177            } else {
178                self.cursor.pop_back();
179            }
180        }
181    }
182}