| .. highlight:: c |
| |
| .. _thread-local-storage: |
| |
| Thread-local storage support |
| ============================ |
| |
| The Python interpreter provides low-level support for thread-local storage |
| (TLS) which wraps the underlying native TLS implementation to support the |
| Python-level thread-local storage API (:class:`threading.local`). The |
| CPython C level APIs are similar to those offered by pthreads and Windows: |
| use a thread key and functions to associate a :c:expr:`void*` value per |
| thread. |
| |
| A :term:`thread state` does *not* need to be :term:`attached <attached thread state>` |
| when calling these functions; they supply their own locking. |
| |
| Note that :file:`Python.h` does not include the declaration of the TLS APIs, |
| you need to include :file:`pythread.h` to use thread-local storage. |
| |
| .. note:: |
| None of these API functions handle memory management on behalf of the |
| :c:expr:`void*` values. You need to allocate and deallocate them yourself. |
| If the :c:expr:`void*` values happen to be :c:expr:`PyObject*`, these |
| functions don't do refcount operations on them either. |
| |
| .. _thread-specific-storage-api: |
| |
| Thread-specific storage API |
| --------------------------- |
| |
| The thread-specific storage (TSS) API was introduced to supersede the use of the existing TLS API within the |
| CPython interpreter. This API uses a new type :c:type:`Py_tss_t` instead of |
| :c:expr:`int` to represent thread keys. |
| |
| .. versionadded:: 3.7 |
| |
| .. seealso:: "A New C-API for Thread-Local Storage in CPython" (:pep:`539`) |
| |
| |
| .. c:type:: Py_tss_t |
| |
| This data structure represents the state of a thread key, the definition of |
| which may depend on the underlying TLS implementation, and it has an |
| internal field representing the key's initialization state. There are no |
| public members in this structure. |
| |
| When :ref:`Py_LIMITED_API <stable>` is not defined, static allocation of |
| this type by :c:macro:`Py_tss_NEEDS_INIT` is allowed. |
| |
| |
| .. c:macro:: Py_tss_NEEDS_INIT |
| |
| This macro expands to the initializer for :c:type:`Py_tss_t` variables. |
| Note that this macro won't be defined with :ref:`Py_LIMITED_API <stable>`. |
| |
| |
| Dynamic allocation |
| ------------------ |
| |
| Dynamic allocation of the :c:type:`Py_tss_t`, required in extension modules |
| built with :ref:`Py_LIMITED_API <stable>`, where static allocation of this type |
| is not possible due to its implementation being opaque at build time. |
| |
| |
| .. c:function:: Py_tss_t* PyThread_tss_alloc() |
| |
| Return a value which is the same state as a value initialized with |
| :c:macro:`Py_tss_NEEDS_INIT`, or ``NULL`` in the case of dynamic allocation |
| failure. |
| |
| |
| .. c:function:: void PyThread_tss_free(Py_tss_t *key) |
| |
| Free the given *key* allocated by :c:func:`PyThread_tss_alloc`, after |
| first calling :c:func:`PyThread_tss_delete` to ensure any associated |
| thread locals have been unassigned. This is a no-op if the *key* |
| argument is ``NULL``. |
| |
| .. note:: |
| A freed key becomes a dangling pointer. You should reset the key to |
| ``NULL``. |
| |
| |
| Methods |
| ------- |
| |
| The parameter *key* of these functions must not be ``NULL``. Moreover, the |
| behaviors of :c:func:`PyThread_tss_set` and :c:func:`PyThread_tss_get` are |
| undefined if the given :c:type:`Py_tss_t` has not been initialized by |
| :c:func:`PyThread_tss_create`. |
| |
| |
| .. c:function:: int PyThread_tss_is_created(Py_tss_t *key) |
| |
| Return a non-zero value if the given :c:type:`Py_tss_t` has been initialized |
| by :c:func:`PyThread_tss_create`. |
| |
| |
| .. c:function:: int PyThread_tss_create(Py_tss_t *key) |
| |
| Return a zero value on successful initialization of a TSS key. The behavior |
| is undefined if the value pointed to by the *key* argument is not |
| initialized by :c:macro:`Py_tss_NEEDS_INIT`. This function can be called |
| repeatedly on the same key -- calling it on an already initialized key is a |
| no-op and immediately returns success. |
| |
| |
| .. c:function:: void PyThread_tss_delete(Py_tss_t *key) |
| |
| Destroy a TSS key to forget the values associated with the key across all |
| threads, and change the key's initialization state to uninitialized. A |
| destroyed key is able to be initialized again by |
| :c:func:`PyThread_tss_create`. This function can be called repeatedly on |
| the same key -- calling it on an already destroyed key is a no-op. |
| |
| |
| .. c:function:: int PyThread_tss_set(Py_tss_t *key, void *value) |
| |
| Return a zero value to indicate successfully associating a :c:expr:`void*` |
| value with a TSS key in the current thread. Each thread has a distinct |
| mapping of the key to a :c:expr:`void*` value. |
| |
| |
| .. c:function:: void* PyThread_tss_get(Py_tss_t *key) |
| |
| Return the :c:expr:`void*` value associated with a TSS key in the current |
| thread. This returns ``NULL`` if no value is associated with the key in the |
| current thread. |
| |
| |
| .. _thread-local-storage-api: |
| |
| Legacy APIs |
| ----------- |
| |
| .. deprecated:: 3.7 |
| This API is superseded by the |
| :ref:`thread-specific storage (TSS) API <thread-specific-storage-api>`. |
| |
| .. note:: |
| This version of the API does not support platforms where the native TLS key |
| is defined in a way that cannot be safely cast to ``int``. On such platforms, |
| :c:func:`PyThread_create_key` will return immediately with a failure status, |
| and the other TLS functions will all be no-ops on such platforms. |
| |
| Due to the compatibility problem noted above, this version of the API should not |
| be used in new code. |
| |
| .. c:function:: int PyThread_create_key() |
| .. c:function:: void PyThread_delete_key(int key) |
| .. c:function:: int PyThread_set_key_value(int key, void *value) |
| .. c:function:: void* PyThread_get_key_value(int key) |
| .. c:function:: void PyThread_delete_key_value(int key) |
| .. c:function:: void PyThread_ReInitTLS() |