Repository navigation
Reduce critical section boilerplate in type slot implementations #114258
Description
Feature or enhancement
PEP 703 in large part relies on replacing the GIL with fine grained per-object locks. The primary way to acquire and release these locks is through the critical section API (#111569). In #111903, we added support for generating the necessary critical section calls in Argument Clinic wrapped methods. In #112205, this was extended to getters and setters as well.
However, some object behavior is implemented using "tp slots", which are not supported by Argument Clinic. These functions often need critical sections for thread-safety; that means more boilerplate code.
Here are some possible ideas on how to address this:
Add support for "tp slots" to Argument Clinic
We could add support for certain tp slots functions to Argument Clinic. This would provide a consistent way to add critical sections across both slots, getters/setters, and "regular" methods. The disadvantage is that "tp slots" don't need much argument parsing, so they may otherwise not be a great fit for Argument Clinic
Use C macros to wrap slot implementations with critical sections
We could implement an internal-only header that provides macros to wrap a given "tp slot" function with a critical section. For example, something like:
static PyObject *
list_richcompare_impl(PyObject *v, PyObject *w, int op)
{
// implement richcompare unchanged
}
// generates a list_richcompare() function with the correct Py_BEGIN/END_CRITICAL_SECTION()
_Py_CRITICAL_SECTION_TP_RICHCOMPARE(list_richcompare, list_richcompare_impl);I think this would not be too difficult to implement -- probably easier than modifying Argument Clinic. The disadvantage is the lack of uniformity around how we add critical sections to functions.
Keep the status quo
We can always just keep adding the Py_BEGIN/END_CRITICAL_SECTION() calls manually for tp slots.
Linked PRs
- gh-114258: Refactor Argument Clinic function name parser #114930
- gh-114258: Argument Clinic: refactor getset implementation #116170
- gh-114258: Update AC to support @critical_section for tp_iternext #159962
- gh-114258: Use Argument Clinic for
__repr__#160011 - gh-114258: Use Argument Clinic for
__len__#160012 - gh-114258: Use Argument Clinic for
__setitem__#160048 - gh-114258: Use Argument Clinic for
__mul__/__imul__#160049 - gh-114258: Use Argument Clinic for
__add__/__iadd__#160051 - gh-114258: Use Argument Clinic for
__bool__#160057 - gh-114258: Use Argument Clinic for
__hash__#160059 - gh-114258: Use Argument Clinic for
__getitem__#160068 - gh-114258: Update Argument Clinic for __contain__ slots #160093
- gh-114258: Update Argument Clinic for
__str__. #160402 - gh-114258: Update _ctypes and tokenize to use AC where it can be. #160404
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsTodo
Activity
pythongh-114258: Argument Clinic: refactor getset implementation (pyt…
pythongh-114258: Argument Clinic: refactor getset implementation (pyt…
corona10 commentedon Oct 20, 2026
cc @ZeroIntensity
corona10 commentedon Oct 20, 2026
Peter and I discussed during the sprint a simple plan like this:
Phase 1: single
@critical_section+ plain Clinic declaration (53)__next____repr____len____bool____hash____getitem__(Py_ssize_t)__getitem__(object)__setitem__(Py_ssize_t)__setitem__(object)__contains____mul____imul____add____iadd__Phase 2:
Py_BEGIN_CRITICAL_SECTION2+ plain Clinic declaration (2)__richcompare__(name TBD)@critical_section self otheralready works; only the dunder name andthe
opparameter need a decision.Phase 3: small migration first, then Clinic (16)
_impl__repr___impl__str___impl__next___impl__bool___impl__contains___impl__release_buffer____next____buffer__Out of scope for now: keep manual (25)
The rest of the case would be handled manually.
pythongh-114258: Update AC to support @critical_section for tp_next
pythongh-114258: Update AC to support @critical_section for tp_iternext
gh-114258: Update AC to support @critical_section for tp_iternext (gh…
gh-114258: Use Argument Clinic for `__len__` (GH-160012)
gh-114258: Use Argument Clinic for `__setitem__` (GH-160048)
Merge remote-tracking branch 'upstream/main' into pythongh-114258-get…
gh-114258: Use Argument Clinic for `__repr__` (GH-160011)
Merge remote-tracking branch 'upstream/main' into pythongh-114258-con…
gh-114258: Use Argument Clinic for `__mul__`/`__imul__` (GH-160049)
gh-114258: Use Argument Clinic for `__add__`/`__iadd__` (GH-160051)
Merge remote-tracking branch 'upstream/main' into pythongh-114258-con…
gh-114258: Update Argument Clinic for __contain__ slots (gh-160093)
Merge remote-tracking branch 'upstream/main' into pythongh-114258-get…
Merge remote-tracking branch 'upstream/main' into pythongh-114258-get…
Merge remote-tracking branch 'upstream/main' into pythongh-114258-hash
gh-114258: Use Argument Clinic for ``__getitem__`` (gh-160068)
Merge branch 'main' of https://github.com/python/cpython into pythong…
gh-114258: Use Argument Clinic for ``__bool__`` (GH-160057)
Merge remote-tracking branch 'upstream/main' into pythongh-114258-hash
gh-114258: Use Argument Clinic for ``__hash__`` (gh-160059)
gh-114258: Update Argument Clinic for ``__str__``. (gh-160402)
gh-114258: Update _ctypes and tokenize to use AC where it can be. (gh…