mirror of
https://github.com/python/cpython.git
synced 2026-02-22 07:00:51 +00:00
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Benedikt Johannes <benedikt.johannes.hofer@gmail.com>
155 lines
5.5 KiB
ReStructuredText
155 lines
5.5 KiB
ReStructuredText
.. 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()
|