futures_util/stream/stream/
flatten_unordered.rs1use alloc::sync::Arc;
2use core::{
3 cell::UnsafeCell,
4 convert::identity,
5 fmt,
6 marker::PhantomData,
7 num::NonZeroUsize,
8 pin::Pin,
9 sync::atomic::{AtomicU8, Ordering},
10};
11
12use pin_project_lite::pin_project;
13
14use futures_core::{
15 future::Future,
16 ready,
17 stream::{FusedStream, Stream},
18 task::{Context, Poll, Waker},
19};
20#[cfg(feature = "sink")]
21use futures_sink::Sink;
22use futures_task::{waker, ArcWake};
23
24use crate::stream::FuturesUnordered;
25
26pub type FlattenUnordered<St> = FlattenUnorderedWithFlowController<St, ()>;
29
30const NONE: u8 = 0;
32
33const NEED_TO_POLL_INNER_STREAMS: u8 = 1;
35
36const NEED_TO_POLL_STREAM: u8 = 0b10;
38
39const NEED_TO_POLL_ALL: u8 = NEED_TO_POLL_INNER_STREAMS | NEED_TO_POLL_STREAM;
41
42const POLLING: u8 = 0b100;
44
45const WAKING: u8 = 0b1000;
47
48const WOKEN: u8 = 0b10000;
50
51#[derive(Clone, Debug)]
53struct SharedPollState {
54 state: Arc<AtomicU8>,
55}
56
57impl SharedPollState {
58 fn new(value: u8) -> Self {
60 Self { state: Arc::new(AtomicU8::new(value)) }
61 }
62
63 fn start_polling(&self) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&Self) -> u8>)> {
66 #[allow(deprecated)] let value = self
68 .state
69 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| {
70 if value & WAKING == NONE {
71 Some(POLLING)
72 } else {
73 None
74 }
75 })
76 .ok()?;
77 let bomb = PollStateBomb::new(self, Self::reset);
78
79 Some((value, bomb))
80 }
81
82 fn start_waking(
87 &self,
88 to_poll: u8,
89 ) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&Self) -> u8>)> {
90 #[allow(deprecated)] let value = self
92 .state
93 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| {
94 let mut next_value = value | to_poll;
95 if value & (WOKEN | POLLING) == NONE {
96 next_value |= WAKING;
97 }
98
99 if next_value != value {
100 Some(next_value)
101 } else {
102 None
103 }
104 })
105 .ok()?;
106
107 if value & (WOKEN | POLLING | WAKING) == NONE {
109 let bomb = PollStateBomb::new(self, Self::stop_waking);
110
111 Some((value, bomb))
112 } else {
113 None
114 }
115 }
116
117 fn stop_polling(&self, to_poll: u8, will_be_woken: bool) -> u8 {
126 #[allow(deprecated)] self.state
128 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut value| {
129 let mut next_value = to_poll;
130
131 value &= NEED_TO_POLL_ALL;
132 if value != NONE || will_be_woken {
133 next_value |= WOKEN;
134 }
135 next_value |= value;
136
137 Some(next_value & !POLLING & !WAKING)
138 })
139 .unwrap()
140 }
141
142 fn stop_waking(&self) -> u8 {
144 #[allow(deprecated)] let value = self
146 .state
147 .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |value| {
148 let next_value = value & !WAKING | WOKEN;
149
150 if next_value != value {
151 Some(next_value)
152 } else {
153 None
154 }
155 })
156 .unwrap_or_else(identity);
157
158 debug_assert!(value & (WOKEN | POLLING | WAKING) == WAKING);
159 value
160 }
161
162 fn reset(&self) -> u8 {
164 self.state.swap(NEED_TO_POLL_ALL, Ordering::SeqCst)
165 }
166}
167
168struct PollStateBomb<'a, F: FnOnce(&SharedPollState) -> u8> {
170 state: &'a SharedPollState,
171 drop: Option<F>,
172}
173
174impl<'a, F: FnOnce(&SharedPollState) -> u8> PollStateBomb<'a, F> {
175 fn new(state: &'a SharedPollState, drop: F) -> Self {
177 Self { state, drop: Some(drop) }
178 }
179
180 fn deactivate(mut self) {
182 self.drop.take();
183 }
184}
185
186impl<F: FnOnce(&SharedPollState) -> u8> Drop for PollStateBomb<'_, F> {
187 fn drop(&mut self) {
188 if let Some(drop) = self.drop.take() {
189 (drop)(self.state);
190 }
191 }
192}
193
194struct WrappedWaker {
197 inner_waker: UnsafeCell<Option<Waker>>,
198 poll_state: SharedPollState,
199 need_to_poll: u8,
200}
201
202unsafe impl Send for WrappedWaker {}
203unsafe impl Sync for WrappedWaker {}
204
205impl WrappedWaker {
206 unsafe fn replace_waker(self_arc: &mut Arc<Self>, cx: &Context<'_>) {
215 unsafe { *self_arc.inner_waker.get() = cx.waker().clone().into() }
216 }
217
218 fn start_waking(&self) -> Option<(u8, PollStateBomb<'_, impl FnOnce(&SharedPollState) -> u8>)> {
221 self.poll_state.start_waking(self.need_to_poll)
222 }
223}
224
225impl ArcWake for WrappedWaker {
226 fn wake_by_ref(self_arc: &Arc<Self>) {
227 if let Some((_, state_bomb)) = self_arc.start_waking() {
228 let waker_opt = unsafe { self_arc.inner_waker.get().as_ref().unwrap() };
230
231 if let Some(inner_waker) = waker_opt.clone() {
232 drop(state_bomb);
234
235 inner_waker.wake();
237 }
238 }
239 }
240}
241
242pin_project! {
243 #[must_use = "futures do nothing unless you `.await` or poll them"]
252 struct PollStreamFut<St> {
253 #[pin]
254 stream: Option<St>,
255 }
256}
257
258impl<St> PollStreamFut<St> {
259 fn new(stream: impl Into<Option<St>>) -> Self {
261 Self { stream: stream.into() }
262 }
263}
264
265impl<St: Stream + Unpin> Future for PollStreamFut<St> {
266 type Output = Option<(St::Item, Self)>;
267
268 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
269 let mut stream = self.project().stream;
270
271 let item = if let Some(stream) = stream.as_mut().as_pin_mut() {
272 ready!(stream.poll_next(cx))
273 } else {
274 None
275 };
276 let next_item_fut = Self::new(stream.get_mut().take());
277 let out = item.map(|item| (item, next_item_fut));
278
279 Poll::Ready(out)
280 }
281}
282
283pin_project! {
284 #[project = FlattenUnorderedWithFlowControllerProj]
287 #[must_use = "streams do nothing unless polled"]
288 pub struct FlattenUnorderedWithFlowController<St, Fc> where St: Stream {
289 #[pin]
290 inner_streams: FuturesUnordered<PollStreamFut<St::Item>>,
291 #[pin]
292 stream: St,
293 poll_state: SharedPollState,
294 limit: Option<NonZeroUsize>,
295 is_stream_done: bool,
296 inner_streams_waker: Arc<WrappedWaker>,
297 stream_waker: Arc<WrappedWaker>,
298 flow_controller: PhantomData<Fc>
299 }
300}
301
302impl<St, Fc> fmt::Debug for FlattenUnorderedWithFlowController<St, Fc>
303where
304 St: Stream + fmt::Debug,
305 St::Item: Stream + fmt::Debug,
306{
307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 f.debug_struct("FlattenUnorderedWithFlowController")
309 .field("poll_state", &self.poll_state)
310 .field("inner_streams", &self.inner_streams)
311 .field("limit", &self.limit)
312 .field("stream", &self.stream)
313 .field("is_stream_done", &self.is_stream_done)
314 .field("flow_controller", &self.flow_controller)
315 .finish()
316 }
317}
318
319impl<St, Fc> FlattenUnorderedWithFlowController<St, Fc>
320where
321 St: Stream,
322 Fc: FlowController<St::Item, <St::Item as Stream>::Item>,
323 St::Item: Stream + Unpin,
324{
325 pub(crate) fn new(stream: St, limit: Option<usize>) -> Self {
326 let poll_state = SharedPollState::new(NEED_TO_POLL_STREAM);
327
328 Self {
329 inner_streams: FuturesUnordered::new(),
330 stream,
331 is_stream_done: false,
332 limit: limit.and_then(NonZeroUsize::new),
333 inner_streams_waker: Arc::new(WrappedWaker {
334 inner_waker: UnsafeCell::new(None),
335 poll_state: poll_state.clone(),
336 need_to_poll: NEED_TO_POLL_INNER_STREAMS,
337 }),
338 stream_waker: Arc::new(WrappedWaker {
339 inner_waker: UnsafeCell::new(None),
340 poll_state: poll_state.clone(),
341 need_to_poll: NEED_TO_POLL_STREAM,
342 }),
343 poll_state,
344 flow_controller: PhantomData,
345 }
346 }
347
348 delegate_access_inner!(stream, St, ());
349}
350
351pub trait FlowController<I, O> {
353 fn next_step(item: I) -> FlowStep<I, O>;
355}
356
357impl<I, O> FlowController<I, O> for () {
358 fn next_step(item: I) -> FlowStep<I, O> {
359 FlowStep::Continue(item)
360 }
361}
362
363#[derive(Debug, Clone)]
365pub enum FlowStep<C, R> {
366 Continue(C),
368 Return(R),
370}
371
372impl<St, Fc> FlattenUnorderedWithFlowControllerProj<'_, St, Fc>
373where
374 St: Stream,
375{
376 fn is_exceeded_limit(&self) -> bool {
378 self.limit.map_or(false, |limit| self.inner_streams.len() >= limit.get())
379 }
380}
381
382impl<St, Fc> FusedStream for FlattenUnorderedWithFlowController<St, Fc>
383where
384 St: FusedStream,
385 Fc: FlowController<St::Item, <St::Item as Stream>::Item>,
386 St::Item: Stream + Unpin,
387{
388 fn is_terminated(&self) -> bool {
389 self.stream.is_terminated() && self.inner_streams.is_empty()
390 }
391}
392
393impl<St, Fc> Stream for FlattenUnorderedWithFlowController<St, Fc>
394where
395 St: Stream,
396 Fc: FlowController<St::Item, <St::Item as Stream>::Item>,
397 St::Item: Stream + Unpin,
398{
399 type Item = <St::Item as Stream>::Item;
400
401 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
402 let mut next_item = None;
403 let mut need_to_poll_next = NONE;
404
405 let mut this = self.as_mut().project();
406
407 let (mut poll_state_value, state_bomb) = loop {
409 if let Some(value) = this.poll_state.start_polling() {
410 break value;
411 }
412 };
413
414 unsafe {
416 WrappedWaker::replace_waker(this.stream_waker, cx);
417 WrappedWaker::replace_waker(this.inner_streams_waker, cx)
418 };
419
420 if poll_state_value & NEED_TO_POLL_STREAM != NONE {
421 let mut stream_waker = None;
422
423 loop {
428 if this.is_exceeded_limit() || *this.is_stream_done {
429 if !*this.is_stream_done {
431 need_to_poll_next |= NEED_TO_POLL_STREAM;
433 }
434
435 break;
436 } else {
437 let mut cx = Context::from_waker(
438 stream_waker.get_or_insert_with(|| waker(this.stream_waker.clone())),
439 );
440
441 match this.stream.as_mut().poll_next(&mut cx) {
442 Poll::Ready(Some(item)) => {
443 let next_item_fut = match Fc::next_step(item) {
444 FlowStep::Return(item) => {
446 need_to_poll_next |= NEED_TO_POLL_STREAM
447 | (poll_state_value & NEED_TO_POLL_INNER_STREAMS);
448 poll_state_value &= !NEED_TO_POLL_INNER_STREAMS;
449
450 next_item = Some(item);
451
452 break;
453 }
454 FlowStep::Continue(inner_stream) => {
456 PollStreamFut::new(inner_stream)
457 }
458 };
459 this.inner_streams.as_mut().push(next_item_fut);
461 poll_state_value |= NEED_TO_POLL_INNER_STREAMS;
463 }
464 Poll::Ready(None) => {
465 *this.is_stream_done = true;
467 }
468 Poll::Pending => {
469 break;
470 }
471 }
472 }
473 }
474 }
475
476 if poll_state_value & NEED_TO_POLL_INNER_STREAMS != NONE {
477 let inner_streams_waker = waker(this.inner_streams_waker.clone());
478 let mut cx = Context::from_waker(&inner_streams_waker);
479
480 match this.inner_streams.as_mut().poll_next(&mut cx) {
481 Poll::Ready(Some(Some((item, next_item_fut)))) => {
482 this.inner_streams.as_mut().push(next_item_fut);
484 next_item = Some(item);
486 need_to_poll_next |= NEED_TO_POLL_INNER_STREAMS;
488 }
489 Poll::Ready(Some(None)) => {
490 need_to_poll_next |= NEED_TO_POLL_INNER_STREAMS;
492 }
493 _ => {}
494 }
495 }
496
497 state_bomb.deactivate();
499
500 let mut force_wake =
502 need_to_poll_next & NEED_TO_POLL_STREAM != NONE && !this.is_exceeded_limit()
504 || need_to_poll_next & NEED_TO_POLL_INNER_STREAMS != NONE;
506
507 poll_state_value = this.poll_state.stop_polling(need_to_poll_next, force_wake);
509 force_wake |= poll_state_value & NEED_TO_POLL_ALL != NONE;
511
512 let is_done = *this.is_stream_done && this.inner_streams.is_empty();
513
514 if next_item.is_some() || is_done {
515 Poll::Ready(next_item)
516 } else {
517 if force_wake {
518 cx.waker().wake_by_ref();
519 }
520
521 Poll::Pending
522 }
523 }
524}
525
526#[cfg(feature = "sink")]
528impl<St, Item, Fc> Sink<Item> for FlattenUnorderedWithFlowController<St, Fc>
529where
530 St: Stream + Sink<Item>,
531{
532 type Error = St::Error;
533
534 delegate_sink!(stream, Item);
535}