Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "how to" for the critical_section Argument Clinic directive. #1217

Merged
merged 3 commits into from
Nov 14, 2023
Merged
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
46 changes: 46 additions & 0 deletions development-tools/clinic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1955,6 +1955,52 @@ The generated docstring ends up looking like this:
Return a copy of the code object with new values for the specified fields.


.. _clinic-howto-critical-sections:

How to use critical sections with Argument Clinic
-------------------------------------------------

You can use the ``@critical_section`` directive to instruct Argument Clinic to
wrap the call to the "impl" function in a "Python critical section".
In builds of CPython without the Global Interpreter Lock ("GIL"),
critical sections are required in order to achieve
thread safety without causing deadlocks between threads.
When a critical section is entered into, a per-object lock associated
with the first argument of the decorated function is acquired.
The lock is released on exiting the critical section.

Python critical sections are no-ops in builds of CPython with the GIL.
See :cpy-file:`Include/internal/pycore_critical_section.h`
and :pep:`PEP 703 <703#python-critical-sections>`
for more details about critical sections.

Example from :cpy-file:`Modules/_io/bufferedio.c`::

/*[clinic input]
@critical_section
_io._Buffered.close
[clinic start generated code]*/

The generated glue code looks like this:

.. code-block:: c

static PyObject *
_io__Buffered_close(buffered *self, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;

Py_BEGIN_CRITICAL_SECTION(self);
return_value = _io__Buffered_close_impl(self);
Py_END_CRITICAL_SECTION();

return return_value;
}


.. versionadded:: 3.13


.. _clinic-howto-deprecate-positional:
.. _clinic-howto-deprecate-keyword:

Expand Down