Skip to content

Commit 56b615e

Browse files
committed
Make itertools.combinations_with_replacement thread-safe
1 parent ccbe41e commit 56b615e

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

Lib/test/test_free_threading/test_itertools.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22
from threading import Thread, Barrier
3-
from itertools import batched, chain, cycle
3+
from itertools import batched, chain, combinations_with_replacement, cycle
44
from test.support import threading_helper
55

66

@@ -89,6 +89,32 @@ def work(it):
8989

9090
barrier.reset()
9191

92+
@threading_helper.reap_threads
93+
def test_combinations_with_replacement(self):
94+
number_of_threads = 6
95+
number_of_iterations = 100
96+
data = tuple(range(3))
97+
98+
barrier = Barrier(number_of_threads)
99+
def work(it):
100+
barrier.wait()
101+
while True:
102+
try:
103+
v = next(it)
104+
except StopIteration:
105+
break
106+
107+
for _ in range(number_of_iterations):
108+
cwr_iterator = combinations_with_replacement(data, 2)
109+
worker_threads = []
110+
for _ in range(number_of_threads):
111+
worker_threads.append(
112+
Thread(target=work, args=[cwr_iterator]))
113+
114+
with threading_helper.start_threads(worker_threads):
115+
pass
116+
117+
barrier.reset()
92118

93119

94120
if __name__ == "__main__":

Modules/itertoolsmodule.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2587,7 +2587,7 @@ cwr_traverse(PyObject *op, visitproc visit, void *arg)
25872587
}
25882588

25892589
static PyObject *
2590-
cwr_next(PyObject *op)
2590+
cwr_next_lock_held(PyObject *op)
25912591
{
25922592
cwrobject *co = cwrobject_CAST(op);
25932593
PyObject *elem;
@@ -2666,6 +2666,16 @@ cwr_next(PyObject *op)
26662666
return NULL;
26672667
}
26682668

2669+
static PyObject *
2670+
cwr_next(PyObject *op)
2671+
{
2672+
PyObject *result;
2673+
Py_BEGIN_CRITICAL_SECTION(op);
2674+
result = cwr_next_lock_held(op);
2675+
Py_END_CRITICAL_SECTION()
2676+
return result;
2677+
}
2678+
26692679
static PyMethodDef cwr_methods[] = {
26702680
{"__sizeof__", cwr_sizeof, METH_NOARGS, sizeof_doc},
26712681
{NULL, NULL} /* sentinel */

0 commit comments

Comments
 (0)