[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)

`