summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio/tasks.py
diff options
context:
space:
mode:
authorItamar Ostricher <itamarost@gmail.com>2023-05-06 15:15:27 (GMT)
committerGitHub <noreply@github.com>2023-05-06 15:15:27 (GMT)
commit263abd333d18b8825cf6d68a5051818826dbffce (patch)
tree9f6eaf466c5bc568ba3d85ba27532c1acc50a3e8 /Lib/asyncio/tasks.py
parent96f95df48e41ccf984de1ee1312c81809fd9e876 (diff)
downloadcpython-263abd333d18b8825cf6d68a5051818826dbffce.zip
cpython-263abd333d18b8825cf6d68a5051818826dbffce.tar.gz
cpython-263abd333d18b8825cf6d68a5051818826dbffce.tar.bz2
gh-104144: Optimize gather to finish eagerly when all futures complete eagerly (#104138)
Diffstat (limited to 'Lib/asyncio/tasks.py')
-rw-r--r--Lib/asyncio/tasks.py13
1 files changed, 12 insertions, 1 deletions
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index aa5269a..7eb647b 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -813,6 +813,7 @@ def gather(*coros_or_futures, return_exceptions=False):
children = []
nfuts = 0
nfinished = 0
+ done_futs = []
loop = None
outer = None # bpo-46672
for arg in coros_or_futures:
@@ -829,7 +830,10 @@ def gather(*coros_or_futures, return_exceptions=False):
nfuts += 1
arg_to_fut[arg] = fut
- fut.add_done_callback(_done_callback)
+ if fut.done():
+ done_futs.append(fut)
+ else:
+ fut.add_done_callback(_done_callback)
else:
# There's a duplicate Future object in coros_or_futures.
@@ -838,6 +842,13 @@ def gather(*coros_or_futures, return_exceptions=False):
children.append(fut)
outer = _GatheringFuture(children, loop=loop)
+ # Run done callbacks after GatheringFuture created so any post-processing
+ # can be performed at this point
+ # optimization: in the special case that *all* futures finished eagerly,
+ # this will effectively complete the gather eagerly, with the last
+ # callback setting the result (or exception) on outer before returning it
+ for fut in done_futs:
+ _done_callback(fut)
return outer