Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions Lib/test/test_free_threading/test_itertools.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,112 @@
import unittest
from threading import Thread, Barrier
from itertools import (
accumulate,
chain,
combinations_with_replacement,
cycle,
permutations,
tee,
zip_longest,
)
from test.support import threading_helper


threading_helper.requires_working_threading(module=True)


def work_iterator(it):
while True:
try:
next(it)
except StopIteration:
break


class ItertoolsThreading(unittest.TestCase):

@threading_helper.reap_threads
def test_cycle(self):
number_of_threads = 6
number_of_iterations = 10
number_of_cycles = 400

barrier = Barrier(number_of_threads)
def work(it):
barrier.wait()
for _ in range(number_of_cycles):
_ = next(it)

data = (1, 2, 3, 4)
for it in range(number_of_iterations):
cycle_iterator = cycle(data)
worker_threads = []
for ii in range(number_of_threads):
worker_threads.append(
Thread(target=work, args=[cycle_iterator]))

with threading_helper.start_threads(worker_threads):
pass

barrier.reset()

@threading_helper.reap_threads
def test_chain(self):
number_of_threads = 6
number_of_iterations = 20

barrier = Barrier(number_of_threads)
def work(it):
barrier.wait()
while True:
try:
next(it)
except StopIteration:
break

data = [(1, )] * 200
for it in range(number_of_iterations):
chain_iterator = chain(*data)
worker_threads = []
for ii in range(number_of_threads):
worker_threads.append(
Thread(target=work, args=[chain_iterator]))

with threading_helper.start_threads(worker_threads):
pass

barrier.reset()

@threading_helper.reap_threads
def test_combinations_with_replacement(self):
number_of_iterations = 6
for _ in range(number_of_iterations):
it = combinations_with_replacement(tuple(range(2)), 2)
threading_helper.run_concurrently(work_iterator, nthreads=6, args=[it])

@threading_helper.reap_threads
def test_permutations(self):
number_of_iterations = 6
for _ in range(number_of_iterations):
it = permutations(tuple(range(2)), 2)
threading_helper.run_concurrently(work_iterator, nthreads=6, args=[it])

@threading_helper.reap_threads
def test_accumulate(self):
number_of_iterations = 10
for _ in range(number_of_iterations):
it = accumulate(tuple(range(40)))
threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it])

@threading_helper.reap_threads
def test_zip_longest(self):
number_of_iterations = 10
for _ in range(number_of_iterations):
it = zip_longest(list(range(4)), list(range(8)), fillvalue=0)
threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it])



class TestTeeConcurrent(unittest.TestCase):
# itertools.tee branches share a linked list of internal data cells.
# Concurrent iteration must not corrupt that shared state or crash the
Expand Down
51 changes: 51 additions & 0 deletions Lib/test/test_free_threading/test_itertools_combinatoric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import unittest
from threading import Thread, Barrier
from itertools import combinations, product
from test.support import threading_helper


threading_helper.requires_working_threading(module=True)

def test_concurrent_iteration(iterator, number_of_threads):
barrier = Barrier(number_of_threads)
def iterator_worker(it):
barrier.wait()
while True:
try:
_ = next(it)
except StopIteration:
return

worker_threads = []
for ii in range(number_of_threads):
worker_threads.append(
Thread(target=iterator_worker, args=[iterator]))

with threading_helper.start_threads(worker_threads):
pass

barrier.reset()

class ItertoolsThreading(unittest.TestCase):

@threading_helper.reap_threads
def test_combinations(self):
number_of_threads = 10
number_of_iterations = 24

for it in range(number_of_iterations):
iterator = combinations((1, 2, 3, 4, 5), 2)
test_concurrent_iteration(iterator, number_of_threads)

@threading_helper.reap_threads
def test_product(self):
number_of_threads = 10
number_of_iterations = 24

for it in range(number_of_iterations):
iterator = product((1, 2, 3, 4, 5), (10, 20, 30))
test_concurrent_iteration(iterator, number_of_threads)


if __name__ == "__main__":
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iterations over :class:`itertools.cycle` safe under free-threading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iterations over :class:`itertools.combinations` and :class:`itertools.product` safe under free-threading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iterations over :class:`itertools.chain` safe under :term:`free threading`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iteration over :class:`itertools.combinations_with_replacement` and :class:`itertools.permutations` safe under free-threading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iteration over :class:`itertools.accumulate` safe under free-threading.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make concurrent iteration over :class:`itertools.zip_longest` safe under free-threading.
Loading
Loading