gh-140476: optimize PySet_Add for frozenset in free-threading (#140440)

Avoids critical section in `PySet_Add` when adding items to newly created frozensets.

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Alper
2025-11-11 12:27:21 -08:00
committed by GitHub
parent b5196fa15a
commit 298e9074cd
2 changed files with 18 additions and 9 deletions

View File

@@ -0,0 +1,2 @@
Optimize :c:func:`PySet_Add` for :class:`frozenset` in :term:`free threaded
<free threading>` build.

View File

@@ -2775,17 +2775,24 @@ PySet_Discard(PyObject *set, PyObject *key)
int
PySet_Add(PyObject *anyset, PyObject *key)
{
if (!PySet_Check(anyset) &&
(!PyFrozenSet_Check(anyset) || !_PyObject_IsUniquelyReferenced(anyset))) {
PyErr_BadInternalCall();
return -1;
if (PySet_Check(anyset)) {
int rv;
Py_BEGIN_CRITICAL_SECTION(anyset);
rv = set_add_key((PySetObject *)anyset, key);
Py_END_CRITICAL_SECTION();
return rv;
}
int rv;
Py_BEGIN_CRITICAL_SECTION(anyset);
rv = set_add_key((PySetObject *)anyset, key);
Py_END_CRITICAL_SECTION();
return rv;
if (PyFrozenSet_Check(anyset) && _PyObject_IsUniquelyReferenced(anyset)) {
// We can only change frozensets if they are uniquely referenced. The
// API limits the usage of `PySet_Add` to "fill in the values of brand
// new frozensets before they are exposed to other code". In this case,
// this can be done without a lock.
return set_add_key((PySetObject *)anyset, key);
}
PyErr_BadInternalCall();
return -1;
}
int