PEP 539: update draft (#316)
This commit is contained in:
parent
14e14c6dce
commit
7a99bb9b72
109
pep-0539.txt
109
pep-0539.txt
|
@ -57,10 +57,6 @@ These would be superseded by a new set of analogous functions::
|
|||
PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t *key, void *value)
|
||||
PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t *key)
|
||||
|
||||
``PyThread_delete_key_value`` and ``PyThread_ReInitTLS`` don't provide
|
||||
on the new TSS API because these functions are for the CPython's own TLS
|
||||
implementation that was removed [8]_.
|
||||
|
||||
The specification also adds a few new features:
|
||||
|
||||
* A new type ``Py_tss_t``--an opaque type the definition of which may
|
||||
|
@ -83,16 +79,26 @@ The specification also adds a few new features:
|
|||
PyAPI_FUNC(void) PyThread_tss_free(Py_tss_t *key)
|
||||
PyAPI_FUNC(bool) PyThread_tss_is_created(Py_tss_t *key)
|
||||
|
||||
The first two are needed for dynamic (de-)allocation of a `Py_tss_t`,
|
||||
particularly in extension modules built with `Py_LIMITED_API`, where
|
||||
The first two are needed for dynamic (de-)allocation of a ``Py_tss_t``,
|
||||
particularly in extension modules built with ``Py_LIMITED_API``, where
|
||||
static allocation of this type is not possible due to its implementation
|
||||
being opaque at build time. The value returned by ``PyThread_tss_alloc``
|
||||
is the same state (not yet initialized key) as statically allocated with
|
||||
``Py_tss_NEEDS_INIT``. ``PyThread_tss_is_created`` returns ``true`` if the
|
||||
given ``Py_tss_t`` has been initialized (i.e. by ``PyThread_tss_create``).
|
||||
being opaque at build time. A value returned by ``PyThread_tss_alloc``
|
||||
is the same state as initialized by ``Py_tss_NEEDS_INIT``, or ``NULL`` for
|
||||
dynamic allocation failure. The behavior of ``PyThread_tss_free`` involves
|
||||
calling ``PyThread_tss_delete`` preventively, or is no-op if the value
|
||||
pointed to by the ``key`` argument is ``NULL``. ``PyThread_tss_is_created``
|
||||
returns ``true`` if the given ``Py_tss_t`` has been initialized (i.e. by
|
||||
``PyThread_tss_create``).
|
||||
|
||||
The new TSS API does not provide functions which correspond to
|
||||
``PyThread_delete_key_value`` and ``PyThread_ReInitTLS``, because these
|
||||
functions are for the removed CPython's own TLS implementation, that is the
|
||||
existing API behavior has become as follows: ``PyThread_delete_key_value(key)``
|
||||
is equal to ``PyThread_set_key_value(key, NULL)``, and ``PyThread_ReInitTLS()``
|
||||
is no-op [8]_.
|
||||
|
||||
The new ``PyThread_tss_`` functions are almost exactly analogous to their
|
||||
original counterparts with a minor difference: Whereas
|
||||
original counterparts with a few minor differences: Whereas
|
||||
``PyThread_create_key`` takes no arguments and returns a TLS key as an
|
||||
``int``, ``PyThread_tss_create`` takes a ``Py_tss_t*`` as an argument and
|
||||
returns an ``int`` status code. The behavior of ``PyThread_tss_create`` is
|
||||
|
@ -105,7 +111,22 @@ Similarly the other ``PyThread_tss_`` functions are passed a ``Py_tss_t*``
|
|||
whereas previously the key was passed by value. This change is necessary, as
|
||||
being an opaque type, the ``Py_tss_t`` type could hypothetically be almost
|
||||
any size. This is especially necessary for extension modules built with
|
||||
``Py_LIMITED_API``, where the size of the type is not known.
|
||||
``Py_LIMITED_API``, where the size of the type is not known. Except for
|
||||
``PyThread_tss_free``, the behaviors of ``PyThread_tss_`` are undefined if the
|
||||
value pointed to by the ``key`` argument is ``NULL``.
|
||||
|
||||
Moreover, because of the use of ``Py_tss_t`` instead of ``int``, there are
|
||||
additional behaviors which the existing API design would be carried over into
|
||||
new API: The TSS key creation and deletion are parts of "do-if-needed" flow
|
||||
and these features are silently skipped if already done--Calling
|
||||
``PyThread_tss_create`` with an initialized key does nothing and returns
|
||||
success soon. This is also the case of calling ``PyThread_tss_delete`` with
|
||||
an uninitialized key.
|
||||
|
||||
The behavior of ``PyThread_tss_delete`` is defined to change the key's
|
||||
initialization state to "uninitialized" in order to restart the CPython
|
||||
interpreter without terminating the process (e.g. embedding Python in an
|
||||
application) [12]_.
|
||||
|
||||
The old ``PyThread_*_key*`` functions will be marked as deprecated in the
|
||||
documentation, but will not generate runtime deprecation warnings.
|
||||
|
@ -114,6 +135,37 @@ Additionally, on platforms where ``sizeof(pthread_key_t) != sizeof(int)``,
|
|||
``PyThread_create_key`` will return immediately with a failure status, and
|
||||
the other TLS functions will all be no-ops on such platforms.
|
||||
|
||||
Comparison of API Specification
|
||||
-------------------------------
|
||||
|
||||
================= ============================= =============================
|
||||
API Thread Local Storage (TLS) Thread Specific Storage (TSS)
|
||||
================= ============================= =============================
|
||||
Version Existing New
|
||||
Key Type ``int`` ``Py_tss_t`` (opaque type)
|
||||
Handle Native Key cast to ``int`` conceal into internal field
|
||||
Function Argument ``int`` ``Py_tss_t *``
|
||||
Features - create key - create key
|
||||
- delete key - delete key
|
||||
- set value - set value
|
||||
- get value - get value
|
||||
- delete value - (set ``NULL`` instead) [8]_
|
||||
- reinitialize keys (for - (unnecessary) [8]_
|
||||
after fork)
|
||||
- dynamically (de-)allocate
|
||||
key
|
||||
- check key's initialization
|
||||
state
|
||||
Default Value (``-1`` as key creation ``Py_tss_NEEDS_INIT``
|
||||
failure)
|
||||
Requirement native thread native thread
|
||||
(since CPython 3.7 [9]_)
|
||||
Restriction Not support platform where Unable to statically allocate
|
||||
native TLS key is defined in key when ``Py_LIMITED_API``
|
||||
a way that cannot be safely is defined.
|
||||
cast to ``int``.
|
||||
================= ============================= =============================
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
|
@ -139,11 +191,22 @@ The rest of the API is used analogously to the old API::
|
|||
PyThread_tss_delete(&tss_key);
|
||||
assert(!PyThread_tss_is_created(&tss_key));
|
||||
|
||||
When ``Py_LIMITED_API`` is defined, a TSS key must be dynamically allocated::
|
||||
|
||||
static Py_tss_t *ptr_key = PyThread_tss_alloc();
|
||||
if (ptr_key == NULL) {
|
||||
/* ... handle key allocation failure ... */
|
||||
}
|
||||
assert(!PyThread_tss_is_created(ptr_key));
|
||||
/* ... once done with the key ... */
|
||||
PyThread_tss_free(ptr_key);
|
||||
ptr_key = NULL;
|
||||
|
||||
|
||||
Platform Support Changes
|
||||
========================
|
||||
|
||||
A new "Native thread implementation" section will be added to PEP 11 that
|
||||
A new "Native Thread Implementation" section will be added to PEP 11 that
|
||||
states:
|
||||
|
||||
* As of CPython 3.7, in the case of enabling thread support, all platforms are
|
||||
|
@ -171,7 +234,7 @@ it was fine for CPython's own TLS implementation, and happens to be
|
|||
compatible with Windows (which uses ``DWORD`` for the analogous data), it is
|
||||
not compatible with the POSIX standard for the pthreads API, which defines
|
||||
``pthread_key_t`` as an opaque type not further defined by the standard (as
|
||||
with ``Py_tss_t`` described above). This leaves it up to the underlying
|
||||
with ``Py_tss_t`` described above) [14]_. This leaves it up to the underlying
|
||||
implementation how a ``pthread_key_t`` value is used to look up
|
||||
thread-specific data.
|
||||
|
||||
|
@ -202,16 +265,23 @@ Rationale for Proposed Solution
|
|||
===============================
|
||||
|
||||
The use of an opaque type (``Py_tss_t``) to key TLS values allows the API to
|
||||
be compatible, with all present (posix and Windows) and future (C11?)
|
||||
be compatible, with all present (POSIX and Windows) and future (C11?)
|
||||
native TLS implementations supported by CPython, as it allows the definition
|
||||
of ``Py_tss_t`` to depend on the underlying implementation.
|
||||
|
||||
Since the existing TLS API has been available in *the limited API* [13]_ for
|
||||
some platforms (e.g. Linux), CPython makes an effort to provide the new TSS API
|
||||
at that level likewise. Note, however, that ``Py_tss_t`` definition becomes to
|
||||
be an opaque struct when ``Py_LIMITED_API`` is defined, because exposing
|
||||
``NATIVE_TSS_KEY_T`` as part of the limited API would prevent us from switching
|
||||
native thread implementation without rebuilding extension module.
|
||||
|
||||
A new API must be introduced, rather than changing the function signatures of
|
||||
the current API, in order to maintain backwards compatibility. The new API
|
||||
also more clearly groups together these related functions under a single name
|
||||
prefix, ``PyThread_tss_``. The "tss" in the name stands for "thread-specific
|
||||
storage", and was influenced by the naming and design of the "tss" API that is
|
||||
part of the C11 threads API. However, this is in no way meant to imply
|
||||
part of the C11 threads API [15]_. However, this is in no way meant to imply
|
||||
compatibility with or support for the C11 threads API, or signal any future
|
||||
intention of supporting C11--it's just the influence for the naming and design.
|
||||
|
||||
|
@ -305,7 +375,12 @@ References and Footnotes
|
|||
.. [5] http://bugs.python.org/file44269/issue25658-1.patch
|
||||
.. [6] http://bugs.python.org/file44303/key-constant-time.diff
|
||||
.. [7] http://bugs.python.org/file46379/pythread-tss-3.patch
|
||||
.. [8] http://bugs.python.org/issue25658#msg298342
|
||||
.. [8] https://bugs.python.org/msg298342
|
||||
.. [9] http://bugs.python.org/issue30832
|
||||
.. [10] https://github.com/python/cpython/compare/master...ma8ma:pep539-tss-api
|
||||
.. [11] https://github.com/python/cpython/pull/1362
|
||||
.. [12] https://docs.python.org/3/c-api/init.html#c.Py_FinalizeEx
|
||||
.. [13] It is also called as "stable ABI"
|
||||
(https://www.python.org/dev/peps/pep-0384/)
|
||||
.. [14] http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_key_create.html
|
||||
.. [15] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=404
|
||||
|
|
Loading…
Reference in New Issue