Skip to content

Commit c7ffc4f

Browse files
committed
refactor
1 parent d7cbe16 commit c7ffc4f

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import unittest
2+
from threading import Thread
3+
4+
from test.support import threading_helper
5+
6+
from itertools import zip_longest
7+
8+
class PairwiseThreading(unittest.TestCase):
9+
@staticmethod
10+
def work(enum):
11+
while True:
12+
try:
13+
next(enum)
14+
except StopIteration:
15+
break
16+
17+
@threading_helper.reap_threads
18+
@threading_helper.requires_working_threading()
19+
def test_zip_longest(self):
20+
number_of_threads = 8
21+
number_of_iterations = 40
22+
n = 200
23+
enum = zip_longest(range(n), range(2*n))
24+
for _ in range(number_of_iterations):
25+
worker_threads = []
26+
for ii in range(number_of_threads):
27+
worker_threads.append(
28+
Thread(
29+
target=self.work,
30+
args=[
31+
enum,
32+
],
33+
)
34+
)
35+
for t in worker_threads:
36+
t.start()
37+
for t in worker_threads:
38+
t.join()
39+
40+
41+
if __name__ == "__main__":
42+
unittest.main()

Modules/itertoolsmodule.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,11 @@ pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
327327
static PyObject *
328328
pairwise_next(pairwiseobject *po)
329329
{
330+
#ifdef Py_GIL_DISABLED
330331
PyObject *it = Py_XNewRef(po->it);
332+
#else
333+
PyObject *it = po->it;
334+
#endif
331335
if (it == NULL) {
332336
return NULL;
333337
}
@@ -339,16 +343,21 @@ pairwise_next(pairwiseobject *po)
339343
old = (*Py_TYPE(it)->tp_iternext)(it);
340344
if (old == NULL) {
341345
Py_CLEAR(po->it);
346+
#ifdef Py_GIL_DISABLED
342347
Py_DECREF(it);
348+
#endif
343349
return NULL;
344350
}
345351
Py_XSETREF(po->old, Py_NewRef(old));
346352
if (po->it == NULL) {
347-
// for re-entrant calls to pairwise next. the actual behavior is not important and this does not avoid any bugs (or does it?)
348-
// the reason for having it is to make the behaviour equal to the python implementation behavior
353+
// gh-109786: special case for re-entrant calls to pairwise next. the actual behavior is not
354+
// important and this does not avoid any bugs (or does it?)
355+
// the reason for having it is to make the behaviour equal to the python implementation
349356
Py_CLEAR(po->old);
350357
Py_DECREF(old);
358+
#ifdef Py_GIL_DISABLED
351359
Py_DECREF(it);
360+
#endif
352361
return NULL;
353362
}
354363
}
@@ -357,7 +366,9 @@ pairwise_next(pairwiseobject *po)
357366
if (new == NULL) {
358367
Py_CLEAR(po->it);
359368
Py_CLEAR(po->old);
369+
#ifdef Py_GIL_DISABLED
360370
Py_DECREF(it);
371+
#endif
361372
Py_DECREF(old);
362373
return NULL;
363374
}
@@ -387,7 +398,9 @@ pairwise_next(pairwiseobject *po)
387398

388399
Py_XSETREF(po->old, new);
389400
Py_DECREF(old); // instead of the decref here we could borrow the reference above
401+
#ifdef Py_GIL_DISABLED
390402
Py_DECREF(it);
403+
#endif
391404
return result;
392405
}
393406

0 commit comments

Comments
 (0)