Skip to content

Commit 0820382

Browse files
MajorBreakfastcramertj
authored andcommitted
Restrict FuturesUnorderdered::iter_mut to Unpin futures. Add iter_pin_mut
1 parent 4584e50 commit 0820382

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

futures-util/src/stream/futures_unordered/iter_mut.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::marker::PhantomData;
1+
use std::marker::{PhantomData, Unpin};
22
use super::FuturesUnordered;
33
use super::node::Node;
44

@@ -10,7 +10,7 @@ pub struct IterMut<'a, F: 'a> {
1010
pub(super) _marker: PhantomData<&'a mut FuturesUnordered<F>>
1111
}
1212

13-
impl<'a, F> Iterator for IterMut<'a, F> {
13+
impl<'a, F: Unpin> Iterator for IterMut<'a, F> {
1414
type Item = &'a mut F;
1515

1616
fn next(&mut self) -> Option<&'a mut F> {
@@ -31,4 +31,4 @@ impl<'a, F> Iterator for IterMut<'a, F> {
3131
}
3232
}
3333

34-
impl<'a, F> ExactSizeIterator for IterMut<'a, F> {}
34+
impl<'a, F: Unpin> ExactSizeIterator for IterMut<'a, F> {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::marker::PhantomData;
2+
use std::mem::PinMut;
3+
4+
use super::FuturesUnordered;
5+
use super::node::Node;
6+
7+
#[derive(Debug)]
8+
/// Mutable iterator over all futures in the unordered set.
9+
pub struct IterPinMut<'a, F: 'a> {
10+
pub(super) node: *const Node<F>,
11+
pub(super) len: usize,
12+
pub(super) _marker: PhantomData<&'a mut FuturesUnordered<F>>
13+
}
14+
15+
impl<'a, F> Iterator for IterPinMut<'a, F> {
16+
type Item = PinMut<'a, F>;
17+
18+
fn next(&mut self) -> Option<PinMut<'a, F>> {
19+
if self.node.is_null() {
20+
return None;
21+
}
22+
unsafe {
23+
let future = (*(*self.node).future.get()).as_mut().unwrap();
24+
let next = *(*self.node).next_all.get();
25+
self.node = next;
26+
self.len -= 1;
27+
Some(PinMut::new_unchecked(future))
28+
}
29+
}
30+
31+
fn size_hint(&self) -> (usize, Option<usize>) {
32+
(self.len, Some(self.len))
33+
}
34+
}
35+
36+
impl<'a, F> ExactSizeIterator for IterPinMut<'a, F> {}

futures-util/src/stream/futures_unordered/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ use futures_core::task::{self, AtomicWaker};
1717
mod abort;
1818
mod ready_to_run_queue;
1919
mod iter_mut;
20+
mod iter_pin_mut;
2021
mod node;
2122

2223
use self::ready_to_run_queue::{ReadyToRunQueue, Dequeue};
2324
use self::iter_mut::IterMut;
25+
use self::iter_pin_mut::IterPinMut;
2426
use self::node::Node;
2527

2628
/// A set of `Future`s which may complete in any order.
@@ -155,6 +157,15 @@ impl<T> FuturesUnordered<T> {
155157
}
156158
}
157159

160+
/// Returns an iterator that allows modifying each future in the set.
161+
pub fn iter_pin_mut<'a>(self: PinMut<'a, Self>) -> IterPinMut<'a, T> {
162+
IterPinMut {
163+
node: self.head_all,
164+
len: self.len,
165+
_marker: PhantomData
166+
}
167+
}
168+
158169
fn release_node(&mut self, node: Arc<Node<T>>) {
159170
// The future is done, try to reset the queued flag. This will prevent
160171
// `notify` from doing any work in the future

0 commit comments

Comments
 (0)