| # Thread safety annotations for C API functions. |
| # |
| # Each line has the form: |
| # function_name : level |
| # |
| # Where level is one of: |
| # incompatible -- not safe even with external locking |
| # compatible -- safe if the caller serializes all access with external locks |
| # distinct -- safe on distinct objects without external synchronization |
| # shared -- safe for concurrent use on the same object |
| # atomic -- atomic |
| # |
| # Lines beginning with '#' are ignored. |
| # The function name must match the C domain identifier used in the documentation. |
| |
| # Synchronization primitives (Doc/c-api/synchronization.rst) |
| PyMutex_Lock:shared: |
| PyMutex_Unlock:shared: |
| PyMutex_IsLocked:atomic: |
| |
| # List objects (Doc/c-api/list.rst) |
| |
| # Type checks - read ob_type pointer, always safe |
| PyList_Check:atomic: |
| PyList_CheckExact:atomic: |
| |
| # Creation - pure allocation, no shared state |
| PyList_New:atomic: |
| |
| # Size - uses atomic load on free-threaded builds |
| PyList_Size:atomic: |
| PyList_GET_SIZE:atomic: |
| |
| # Strong-reference lookup - lock-free with atomic ops |
| PyList_GetItemRef:atomic: |
| |
| # Borrowed-reference lookups - no locking; returned borrowed |
| # reference is unsafe in free-threaded builds without |
| # external synchronization |
| PyList_GetItem:compatible: |
| PyList_GET_ITEM:compatible: |
| |
| # Single-item mutations - hold per-object lock for duration; |
| # appear atomic to lock-free readers |
| PyList_SetItem:atomic: |
| PyList_Append:atomic: |
| |
| # Insert - protected by per-object critical section; shifts |
| # elements so lock-free readers may observe intermediate states |
| PyList_Insert:shared: |
| |
| # Initialization macro - no synchronization; normally only used |
| # to fill in new lists where there is no previous content |
| PyList_SET_ITEM:compatible: |
| |
| # Bulk operations - hold per-object lock for duration |
| PyList_GetSlice:atomic: |
| PyList_AsTuple:atomic: |
| PyList_Clear:atomic: |
| |
| # Reverse - protected by per-object critical section; swaps |
| # elements so lock-free readers may observe intermediate states |
| PyList_Reverse:shared: |
| |
| # Slice assignment - lock target list; also lock source when it |
| # is a list |
| PyList_SetSlice:shared: |
| |
| # Sort - per-object lock held; the list is emptied before sorting |
| # so other threads may observe an empty list, but they won't see the |
| # intermediate states of the sort |
| PyList_Sort:shared: |
| |
| # Extend - lock target list; also lock source when it is a |
| # list, set, or dict |
| PyList_Extend:shared: |
| |
| # Creation - pure allocation, no shared state |
| PyBytes_FromString:atomic: |
| PyBytes_FromStringAndSize:atomic: |
| PyBytes_DecodeEscape:atomic: |
| |
| # Creation from formatting C primitives - pure allocation, no shared state |
| PyBytes_FromFormat:atomic: |
| PyBytes_FromFormatV:atomic: |
| |
| # Creation from object - uses buffer protocol so may call arbitrary code; |
| # safe as long as the buffer is not mutated by another thread during the operation |
| PyBytes_FromObject:shared: |
| |
| # Size - uses atomic load on free-threaded builds |
| PyBytes_Size:atomic: |
| PyBytes_GET_SIZE:atomic: |
| |
| # Raw data - no locking; mutating it is unsafe if the bytes object is shared between threads |
| PyBytes_AsString:compatible: |
| PyBytes_AS_STRING:compatible: |
| PyBytes_AsStringAndSize:compatible: |
| |
| # Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation |
| PyBytes_Concat:shared: |
| PyBytes_ConcatAndDel:shared: |
| PyBytes_Join:shared: |
| |
| # Resizing - safe if the object is unique |
| _PyBytes_Resize:distinct: |
| |
| # Repr - atomic as bytes are immutable |
| PyBytes_Repr:atomic: |
| |
| # Creation from object - may call arbitrary code |
| PyByteArray_FromObject:shared: |
| |
| # Creation - pure allocation, no shared state |
| PyByteArray_FromStringAndSize:atomic: |
| |
| # Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation |
| PyByteArray_Concat:shared: |
| |
| # Size - uses atomic load on free-threaded builds |
| PyByteArray_Size:atomic: |
| PyByteArray_GET_SIZE:atomic: |
| |
| # Raw data - no locking; mutating it is unsafe if the bytearray object is shared between threads |
| PyByteArray_AsString:compatible: |
| PyByteArray_AS_STRING:compatible: |