[3.6] Fix a c.f.as_completed() refleak previously introduced in bpo-2… · python/cpython@5cbca02 (original) (raw)
`@@ -171,15 +171,24 @@ def _create_and_install_waiters(fs, return_when):
`
171
171
`return waiter
`
172
172
``
173
173
``
174
``
`-
def _yield_and_decref(fs, ref_collect):
`
``
174
`+
def _yield_finished_futures(fs, waiter, ref_collect):
`
175
175
`"""
`
176
``
`-
Iterate on the list fs, yielding objects one by one in reverse order.
`
177
``
`-
Before yielding an object, it is removed from each set in
`
178
``
`-
the collection of sets ref_collect.
`
``
176
`+
Iterate on the list fs, yielding finished futures one by one in
`
``
177
`+
reverse order.
`
``
178
`+
Before yielding a future, waiter is removed from its waiters
`
``
179
`+
and the future is removed from each set in the collection of sets
`
``
180
`+
ref_collect.
`
``
181
+
``
182
`+
The aim of this function is to avoid keeping stale references after
`
``
183
`+
the future is yielded and before the iterator resumes.
`
179
184
` """
`
180
185
`while fs:
`
``
186
`+
f = fs[-1]
`
181
187
`for futures_set in ref_collect:
`
182
``
`-
futures_set.remove(fs[-1])
`
``
188
`+
futures_set.remove(f)
`
``
189
`+
with f._condition:
`
``
190
`+
f._waiters.remove(waiter)
`
``
191
`+
del f
`
183
192
`# Careful not to keep a reference to the popped value
`
184
193
`yield fs.pop()
`
185
194
``
`@@ -216,7 +225,8 @@ def as_completed(fs, timeout=None):
`
216
225
`waiter = _create_and_install_waiters(fs, _AS_COMPLETED)
`
217
226
`finished = list(finished)
`
218
227
`try:
`
219
``
`-
yield from _yield_and_decref(finished, ref_collect=(fs,))
`
``
228
`+
yield from _yield_finished_futures(finished, waiter,
`
``
229
`+
ref_collect=(fs,))
`
220
230
``
221
231
`while pending:
`
222
232
`if timeout is None:
`
`@@ -237,9 +247,11 @@ def as_completed(fs, timeout=None):
`
237
247
``
238
248
`# reverse to keep finishing order
`
239
249
`finished.reverse()
`
240
``
`-
yield from _yield_and_decref(finished, ref_collect=(fs, pending))
`
``
250
`+
yield from _yield_finished_futures(finished, waiter,
`
``
251
`+
ref_collect=(fs, pending))
`
241
252
``
242
253
`finally:
`
``
254
`+
Remove waiter from unfinished futures
`
243
255
`for f in fs:
`
244
256
`with f._condition:
`
245
257
`f._waiters.remove(waiter)
`