bpo-20369: concurrent.futures.wait() now deduplicates futures given a… · python/cpython@7d7817c (original) (raw)
4 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -444,7 +444,8 @@ Module Functions | ||
444 | 444 | .. function:: wait(fs, timeout=None, return_when=ALL_COMPLETED) |
445 | 445 | |
446 | 446 | Wait for the :class:`Future` instances (possibly created by different |
447 | -:class:`Executor` instances) given by *fs* to complete. Returns a named | |
447 | +:class:`Executor` instances) given by *fs* to complete. Duplicate futures | |
448 | + given to *fs* are removed and will be returned only once. Returns a named | |
448 | 449 | 2-tuple of sets. The first set, named ``done``, contains the futures that |
449 | 450 | completed (finished or cancelled futures) before the wait completed. The |
450 | 451 | second set, named ``not_done``, contains the futures that did not complete |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -282,13 +282,14 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): | ||
282 | 282 | A named 2-tuple of sets. The first set, named 'done', contains the |
283 | 283 | futures that completed (is finished or cancelled) before the wait |
284 | 284 | completed. The second set, named 'not_done', contains uncompleted |
285 | - futures. | |
285 | + futures. Duplicate futures given to *fs* are removed and will be | |
286 | + returned only once. | |
286 | 287 | """ |
288 | +fs = set(fs) | |
287 | 289 | with _AcquireFutures(fs): |
288 | -done = set(f for f in fs | |
289 | -if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]) | |
290 | -not_done = set(fs) - done | |
291 | - | |
290 | +done = {f for f in fs | |
291 | +if f._state in [CANCELLED_AND_NOTIFIED, FINISHED]} | |
292 | +not_done = fs - done | |
292 | 293 | if (return_when == FIRST_COMPLETED) and done: |
293 | 294 | return DoneAndNotDoneFutures(done, not_done) |
294 | 295 | elif (return_when == FIRST_EXCEPTION) and done: |
@@ -307,7 +308,7 @@ def wait(fs, timeout=None, return_when=ALL_COMPLETED): | ||
307 | 308 | f._waiters.remove(waiter) |
308 | 309 | |
309 | 310 | done.update(waiter.finished_futures) |
310 | -return DoneAndNotDoneFutures(done, set(fs) - done) | |
311 | +return DoneAndNotDoneFutures(done, fs - done) | |
311 | 312 | |
312 | 313 | class Future(object): |
313 | 314 | """Represents the result of an asynchronous computation.""" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -578,6 +578,14 @@ def test_shutdown_no_wait(self): | ||
578 | 578 | |
579 | 579 | |
580 | 580 | class WaitTests: |
581 | +def test_20369(self): | |
582 | +# See https://bugs.python.org/issue20369 | |
583 | +future = self.executor.submit(time.sleep, 1.5) | |
584 | +done, not_done = futures.wait([future, future], | |
585 | +return_when=futures.ALL_COMPLETED) | |
586 | +self.assertEqual({future}, done) | |
587 | +self.assertEqual(set(), not_done) | |
588 | + | |
581 | 589 | |
582 | 590 | def test_first_completed(self): |
583 | 591 | future1 = self.executor.submit(mul, 21, 2) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
1 | +:func:`concurrent.futures.wait` no longer blocks forever when given duplicate Futures. Patch by Kumar Aditya. |