]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-142518: add thread safety annotations for tuple C-API (#148012)
authorKumar Aditya <kumaraditya@python.org>
Tue, 7 Apr 2026 20:25:44 +0000 (01:55 +0530)
committerGitHub <noreply@github.com>
Tue, 7 Apr 2026 20:25:44 +0000 (01:55 +0530)
Doc/c-api/tuple.rst
Doc/data/threadsafety.dat

index 3e3752696c46d899463f249eb9d45afba32d69c4..ba4c6b93de4c11ec27716eb9f35ecf0e467516e5 100644 (file)
@@ -99,7 +99,8 @@ Tuple Objects
 
    Insert a reference to object *o* at position *pos* of the tuple pointed to by
    *p*.  Return ``0`` on success.  If *pos* is out of bounds, return ``-1``
-   and set an :exc:`IndexError` exception.
+   and set an :exc:`IndexError` exception. This function should only be used to fill in brand new tuples;
+   using it on an existing tuple is thread-unsafe.
 
    .. note::
 
@@ -110,7 +111,7 @@ Tuple Objects
 .. c:function:: void PyTuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o)
 
    Like :c:func:`PyTuple_SetItem`, but does no error checking, and should *only* be
-   used to fill in brand new tuples.
+   used to fill in brand new tuples, using it on an existing tuple is thread-unsafe.
 
    Bounds checking is performed as an assertion if Python is built in
    :ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
@@ -236,6 +237,8 @@ type.
 .. c:function:: PyObject* PyStructSequence_GetItem(PyObject *p, Py_ssize_t pos)
 
    Return the object at position *pos* in the struct sequence pointed to by *p*.
+   The returned reference is borrowed from the struct sequence *p*
+   (that is: it is only valid as long as you hold a reference to *p*).
 
    Bounds checking is performed as an assertion if Python is built in
    :ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
index 82edd1167ef1282786cf2424ee6a8b0886b9aebb..7c381ecb70c8363cbb6b0587d5613798bbdb6b6c 100644 (file)
@@ -153,3 +153,48 @@ PyCapsule_SetContext:distinct:
 # Import - looks up a capsule from a module attribute and
 # calls PyCapsule_GetPointer; may call arbitrary code
 PyCapsule_Import:compatible:
+
+# Tuple objects
+
+# Creation - pure allocation, no shared state
+PyTuple_New:atomic:
+PyTuple_FromArray:atomic:
+PyTuple_Pack:atomic:
+
+# Size - tuples are immutable so size never changes
+PyTuple_Size:atomic:
+PyTuple_GET_SIZE:atomic:
+
+# Borrowed-reference lookups - tuples are immutable so items
+# never change, however the tuple must be kept alive while using the borrowed reference
+PyTuple_GetItem:compatible:
+PyTuple_GET_ITEM:compatible:
+
+# Slice - creates a new tuple from an existing tuple
+PyTuple_GetSlice:atomic:
+
+# SetItem - only usable on tuples with refcount 1
+PyTuple_SetItem:compatible:
+PyTuple_SET_ITEM:compatible:
+
+# Resize - only usable on tuples with refcount 1
+_PyTuple_Resize:compatible:
+
+# Struct Sequence objects
+
+# Creation
+PyStructSequence_NewType:atomic:
+PyStructSequence_New:atomic:
+
+# Initialization - modifies the type object in place
+PyStructSequence_InitType:distinct:
+PyStructSequence_InitType2:distinct:
+
+# Borrowed-reference lookups - same as tuple items
+PyStructSequence_GetItem:compatible:
+PyStructSequence_GET_ITEM:compatible:
+
+# SetItem - only for filling in brand new instances
+PyStructSequence_SetItem:compatible:
+PyStructSequence_SET_ITEM:compatible:
+