Skip to content

Commit 64c417d

Browse files
authored
gh-112075: Remove critical section in dict.get (gh-129336)
The `dict.get` implementation uses `_Py_dict_lookup_threadsafe`, which is thread-safe, so we remove the critical section from the argument clinic. Add a test for concurrent dict get and set operations.
1 parent a4459c3 commit 64c417d

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

Lib/test/test_free_threading/test_dict.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from ast import Or
77
from functools import partial
8-
from threading import Thread
8+
from threading import Barrier, Thread
99
from unittest import TestCase
1010

1111
try:
@@ -142,6 +142,27 @@ def writer_func(l):
142142
for ref in thread_list:
143143
self.assertIsNone(ref())
144144

145+
def test_racing_get_set_dict(self):
146+
"""Races getting and setting a dict should be thread safe"""
147+
THREAD_COUNT = 10
148+
barrier = Barrier(THREAD_COUNT)
149+
def work(d):
150+
barrier.wait()
151+
for _ in range(1000):
152+
d[10] = 0
153+
d.get(10, None)
154+
_ = d[10]
155+
156+
d = {}
157+
worker_threads = []
158+
for ii in range(THREAD_COUNT):
159+
worker_threads.append(Thread(target=work, args=[d]))
160+
for t in worker_threads:
161+
t.start()
162+
for t in worker_threads:
163+
t.join()
164+
165+
145166
def test_racing_set_object_dict(self):
146167
"""Races assigning to __dict__ should be thread safe"""
147168
class C: pass

Objects/clinic/dictobject.c.h

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/dictobject.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4248,7 +4248,6 @@ dict___contains__(PyDictObject *self, PyObject *key)
42484248
}
42494249

42504250
/*[clinic input]
4251-
@critical_section
42524251
dict.get
42534252
42544253
key: object
@@ -4260,7 +4259,7 @@ Return the value for key if key is in the dictionary, else default.
42604259

42614260
static PyObject *
42624261
dict_get_impl(PyDictObject *self, PyObject *key, PyObject *default_value)
4263-
/*[clinic end generated code: output=bba707729dee05bf input=a631d3f18f584c60]*/
4262+
/*[clinic end generated code: output=bba707729dee05bf input=279ddb5790b6b107]*/
42644263
{
42654264
PyObject *val = NULL;
42664265
Py_hash_t hash;

0 commit comments

Comments
 (0)