66use  crate :: task:: AtomicWaker ; 
77use  alloc:: sync:: { Arc ,  Weak } ; 
88use  core:: cell:: UnsafeCell ; 
9+ use  core:: cmp; 
910use  core:: fmt:: { self ,  Debug } ; 
1011use  core:: iter:: FromIterator ; 
1112use  core:: marker:: PhantomData ; 
@@ -30,6 +31,33 @@ use self::task::Task;
3031mod  ready_to_run_queue; 
3132use  self :: ready_to_run_queue:: { Dequeue ,  ReadyToRunQueue } ; 
3233
34+ /// Constant used for a `FuturesUnordered` to determine how many times it is 
35+ /// allowed to poll underlying futures without yielding. 
36+ /// 
37+ /// A single call to `poll_next` may potentially do a lot of work before 
38+ /// yielding. This happens in particular if the underlying futures are awoken 
39+ /// frequently but continue to return `Pending`. This is problematic if other 
40+ /// tasks are waiting on the executor, since they do not get to run. This value 
41+ /// caps the number of calls to `poll` on underlying futures a single call to 
42+ /// `poll_next` is allowed to make. 
43+ /// 
44+ /// The value itself is chosen somewhat arbitrarily. It needs to be high enough 
45+ /// that amortize wakeup and scheduling costs, but low enough that we do not 
46+ /// starve other tasks for long. 
47+ /// 
48+ /// See also https://github.com/rust-lang/futures-rs/issues/2047. 
49+ /// 
50+ /// Note that using the length of the `FuturesUnordered` instead of this value 
51+ /// may cause problems if the number of futures is large. 
52+ /// See also https://github.com/rust-lang/futures-rs/pull/2527. 
53+ /// 
54+ /// Additionally, polling the same future twice per iteration may cause another 
55+ /// problem. So, when using this value, it is necessary to limit the max value 
56+ /// based on the length of the `FuturesUnordered`. 
57+ /// (e.g., `cmp::min(self.len(), YIELD_EVERY)`) 
58+ /// See also https://github.com/rust-lang/futures-rs/pull/2333. 
59+ const  YIELD_EVERY :  usize  = 32 ; 
60+ 
3361/// A set of futures which may complete in any order. 
3462/// 
3563/// This structure is optimized to manage a large number of futures. 
@@ -383,21 +411,8 @@ impl<Fut: Future> Stream for FuturesUnordered<Fut> {
383411    type  Item  = Fut :: Output ; 
384412
385413    fn  poll_next ( mut  self :  Pin < & mut  Self > ,  cx :  & mut  Context < ' _ > )  -> Poll < Option < Self :: Item > >  { 
386-         // Variable to determine how many times it is allowed to poll underlying 
387-         // futures without yielding. 
388-         // 
389-         // A single call to `poll_next` may potentially do a lot of work before 
390-         // yielding. This happens in particular if the underlying futures are awoken 
391-         // frequently but continue to return `Pending`. This is problematic if other 
392-         // tasks are waiting on the executor, since they do not get to run. This value 
393-         // caps the number of calls to `poll` on underlying futures a single call to 
394-         // `poll_next` is allowed to make. 
395-         // 
396-         // The value is the length of FuturesUnordered. This ensures that each 
397-         // future is polled only once at most per iteration. 
398-         // 
399-         // See also https://github.com/rust-lang/futures-rs/issues/2047. 
400-         let  yield_every = self . len ( ) ; 
414+         // See YIELD_EVERY docs for more. 
415+         let  yield_every = cmp:: min ( self . len ( ) ,  YIELD_EVERY ) ; 
401416
402417        // Keep track of how many child futures we have polled, 
403418        // in case we want to forcibly yield. 
0 commit comments