Skip to content

Commit 03d712e

Browse files
gh-142518: add thread safety annotations for tuple C-API (#148012)
1 parent d518f15 commit 03d712e

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

Doc/c-api/tuple.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ Tuple Objects
9999
100100
Insert a reference to object *o* at position *pos* of the tuple pointed to by
101101
*p*. Return ``0`` on success. If *pos* is out of bounds, return ``-1``
102-
and set an :exc:`IndexError` exception.
102+
and set an :exc:`IndexError` exception. This function should only be used to fill in brand new tuples;
103+
using it on an existing tuple is thread-unsafe.
103104
104105
.. note::
105106
@@ -110,7 +111,7 @@ Tuple Objects
110111
.. c:function:: void PyTuple_SET_ITEM(PyObject *p, Py_ssize_t pos, PyObject *o)
111112
112113
Like :c:func:`PyTuple_SetItem`, but does no error checking, and should *only* be
113-
used to fill in brand new tuples.
114+
used to fill in brand new tuples, using it on an existing tuple is thread-unsafe.
114115
115116
Bounds checking is performed as an assertion if Python is built in
116117
:ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.
@@ -236,6 +237,8 @@ type.
236237
.. c:function:: PyObject* PyStructSequence_GetItem(PyObject *p, Py_ssize_t pos)
237238
238239
Return the object at position *pos* in the struct sequence pointed to by *p*.
240+
The returned reference is borrowed from the struct sequence *p*
241+
(that is: it is only valid as long as you hold a reference to *p*).
239242
240243
Bounds checking is performed as an assertion if Python is built in
241244
:ref:`debug mode <debug-build>` or :option:`with assertions <--with-assertions>`.

Doc/data/threadsafety.dat

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,48 @@ PyCapsule_SetContext:distinct:
153153
# Import - looks up a capsule from a module attribute and
154154
# calls PyCapsule_GetPointer; may call arbitrary code
155155
PyCapsule_Import:compatible:
156+
157+
# Tuple objects
158+
159+
# Creation - pure allocation, no shared state
160+
PyTuple_New:atomic:
161+
PyTuple_FromArray:atomic:
162+
PyTuple_Pack:atomic:
163+
164+
# Size - tuples are immutable so size never changes
165+
PyTuple_Size:atomic:
166+
PyTuple_GET_SIZE:atomic:
167+
168+
# Borrowed-reference lookups - tuples are immutable so items
169+
# never change, however the tuple must be kept alive while using the borrowed reference
170+
PyTuple_GetItem:compatible:
171+
PyTuple_GET_ITEM:compatible:
172+
173+
# Slice - creates a new tuple from an existing tuple
174+
PyTuple_GetSlice:atomic:
175+
176+
# SetItem - only usable on tuples with refcount 1
177+
PyTuple_SetItem:compatible:
178+
PyTuple_SET_ITEM:compatible:
179+
180+
# Resize - only usable on tuples with refcount 1
181+
_PyTuple_Resize:compatible:
182+
183+
# Struct Sequence objects
184+
185+
# Creation
186+
PyStructSequence_NewType:atomic:
187+
PyStructSequence_New:atomic:
188+
189+
# Initialization - modifies the type object in place
190+
PyStructSequence_InitType:distinct:
191+
PyStructSequence_InitType2:distinct:
192+
193+
# Borrowed-reference lookups - same as tuple items
194+
PyStructSequence_GetItem:compatible:
195+
PyStructSequence_GET_ITEM:compatible:
196+
197+
# SetItem - only for filling in brand new instances
198+
PyStructSequence_SetItem:compatible:
199+
PyStructSequence_SET_ITEM:compatible:
200+

0 commit comments

Comments
 (0)