Skip to content

Commit 08e4733

Browse files
SrTobicramertj
authored andcommitted
process subsequent futures when partially progressing a pool
fixes #1737
1 parent ac81046 commit 08e4733

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

futures-executor/src/local_pool.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,20 @@ impl LocalPool {
184184
/// Though only one task will be completed, progress may be made on multiple tasks.
185185
pub fn try_run_one(&mut self) -> bool {
186186
poll_executor(|ctx| {
187-
let ret = self.poll_pool_once(ctx);
187+
loop {
188+
let ret = self.poll_pool_once(ctx);
188189

189-
// return if we really have executed a future
190-
match ret {
191-
Poll::Ready(Some(_)) => true,
192-
_ => false
190+
// return if we have executed a future
191+
if let Poll::Ready(Some(_)) = ret {
192+
return true;
193+
}
194+
195+
// if there are no new incoming futures
196+
// then there is no feature that can make progress
197+
// and we can return without having completed a single future
198+
if self.incoming.borrow().is_empty() {
199+
return false;
200+
}
193201
}
194202
})
195203
}
@@ -220,17 +228,9 @@ impl LocalPool {
220228
/// of the pool's run or poll methods. While the function is running, all tasks
221229
/// in the pool will try to make progress.
222230
pub fn run_until_stalled(&mut self) {
223-
poll_executor(|ctx| {
224-
loop {
225-
let result = self.poll_pool_once(ctx);
226-
227-
// if there are no more ready futures exit
228-
match result {
229-
Poll::Pending | Poll::Ready(None) => return,
230-
_ => continue
231-
}
232-
}
233-
})
231+
poll_executor(|ctx| {
232+
let _ = self.poll_pool(ctx);
233+
});
234234
}
235235

236236
// Make maximal progress on the entire pool of spawned task, returning `Ready`

futures-executor/tests/local_pool.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,29 @@ fn try_run_one_returns_on_no_progress() {
179179
assert_eq!(cnt.get(), ITER);
180180
}
181181

182+
#[test]
183+
fn try_run_one_runs_sub_futures() {
184+
let mut pool = LocalPool::new();
185+
let mut spawn = pool.spawner();
186+
let cnt = Rc::new(Cell::new(0));
187+
188+
let mut inner_spawner = spawn.clone();
189+
let cnt1 = cnt.clone();
190+
spawn.spawn_local_obj(Box::pin(poll_fn(move |_| {
191+
cnt1.set(cnt1.get() + 1);
192+
193+
let cnt2 = cnt1.clone();
194+
inner_spawner.spawn_local_obj(Box::pin(lazy(move |_|{
195+
cnt2.set(cnt2.get() + 1)
196+
})).into()).unwrap();
197+
198+
Poll::Pending
199+
})).into()).unwrap();
200+
201+
pool.try_run_one();
202+
assert_eq!(cnt.get(), 2);
203+
}
204+
182205
#[test]
183206
fn run_until_stalled_returns_if_empty() {
184207
let mut pool = LocalPool::new();
@@ -203,6 +226,29 @@ fn run_until_stalled_returns_multiple_times() {
203226
assert_eq!(cnt.get(), 2);
204227
}
205228

229+
#[test]
230+
fn run_until_stalled_runs_spawned_sub_futures() {
231+
let mut pool = LocalPool::new();
232+
let mut spawn = pool.spawner();
233+
let cnt = Rc::new(Cell::new(0));
234+
235+
let mut inner_spawner = spawn.clone();
236+
let cnt1 = cnt.clone();
237+
spawn.spawn_local_obj(Box::pin(poll_fn(move |_| {
238+
cnt1.set(cnt1.get() + 1);
239+
240+
let cnt2 = cnt1.clone();
241+
inner_spawner.spawn_local_obj(Box::pin(lazy(move |_|{
242+
cnt2.set(cnt2.get() + 1)
243+
})).into()).unwrap();
244+
245+
Poll::Pending
246+
})).into()).unwrap();
247+
248+
pool.run_until_stalled();
249+
assert_eq!(cnt.get(), 2);
250+
}
251+
206252
#[test]
207253
fn run_until_stalled_executes_all_ready() {
208254
const ITER: usize = 200;

0 commit comments

Comments
 (0)