Skip to content

Commit 2eb25b1

Browse files
committed
gh-116738: Make bisect module thread-safe
1 parent b6d3242 commit 2eb25b1

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import unittest
2+
3+
from itertools import cycle
4+
5+
from test.support import import_helper, threading_helper, subTests
6+
from test.support.threading_helper import run_concurrently
7+
8+
bisect = import_helper.import_module("bisect")
9+
10+
11+
NTHREADS = 10
12+
13+
14+
@threading_helper.requires_working_threading()
15+
class TestBisect(unittest.TestCase):
16+
@subTests("insort_func", [bisect.insort_left, bisect.insort_right])
17+
def test_racing_insort(self, insort_func):
18+
lst = list(range(10))
19+
insort_items_iter = cycle(list(range(11)))
20+
21+
def worker(lst, insort_items_iter):
22+
for _ in range(10):
23+
insort_item = next(insort_items_iter)
24+
insort_func(lst, insort_item)
25+
26+
run_concurrently(
27+
worker_func=worker,
28+
nthreads=NTHREADS,
29+
args=(lst, insort_items_iter),
30+
)
31+
32+
self.assertTrue(self.is_sorted_ascending(lst))
33+
34+
@staticmethod
35+
def is_sorted_ascending(lst):
36+
"""
37+
Check if the list is sorted in ascending order (non-decreasing).
38+
"""
39+
return all(lst[i - 1] <= lst[i] for i in range(1, len(lst)))
40+
41+
42+
if __name__ == "__main__":
43+
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make functions in :mod:`bisect` thread-safe on the :term:`free threaded
2+
<free threading>` build.

Modules/_bisectmodule.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ _bisect_bisect_right_impl(PyObject *module, PyObject *a, PyObject *x,
179179
}
180180

181181
/*[clinic input]
182+
@critical_section a
182183
_bisect.insort_right
183184
184185
a: object
@@ -201,7 +202,7 @@ A custom key function can be supplied to customize the sort order.
201202
static PyObject *
202203
_bisect_insort_right_impl(PyObject *module, PyObject *a, PyObject *x,
203204
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
204-
/*[clinic end generated code: output=ac3bf26d07aedda2 input=f60777d2b6ddb239]*/
205+
/*[clinic end generated code: output=ac3bf26d07aedda2 input=93bd855be0c1add7]*/
205206
{
206207
PyObject *result, *key_x;
207208
Py_ssize_t index;
@@ -365,6 +366,7 @@ _bisect_bisect_left_impl(PyObject *module, PyObject *a, PyObject *x,
365366

366367

367368
/*[clinic input]
369+
@critical_section a
368370
_bisect.insort_left
369371
370372
a: object
@@ -387,7 +389,7 @@ A custom key function can be supplied to customize the sort order.
387389
static PyObject *
388390
_bisect_insort_left_impl(PyObject *module, PyObject *a, PyObject *x,
389391
Py_ssize_t lo, Py_ssize_t hi, PyObject *key)
390-
/*[clinic end generated code: output=b1d33e5e7ffff11e input=0a700a82edbd472c]*/
392+
/*[clinic end generated code: output=b1d33e5e7ffff11e input=93e06f5a323e09ef]*/
391393
{
392394
PyObject *result, *key_x;
393395
Py_ssize_t index;

Modules/clinic/_bisectmodule.c.h

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)