diff options
author | scoder <stefan_ml@behnel.de> | 2017-10-31 11:34:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-31 11:34:37 +0100 |
commit | 4ca8669dd5d125ac901e0b20810496b1884ea8b1 (patch) | |
tree | 5a80848f18f99d8e54650c88359f8c54282c057e | |
parent | aeeef39da6a9a136c6880974589fa5bdb277e8d6 (diff) | |
parent | 4920f701758e36a724eefd5840ab7106c23a51e2 (diff) | |
download | cython-4ca8669dd5d125ac901e0b20810496b1884ea8b1.tar.gz |
Merge pull request #1939 from sonots/tss_api
[WIP] Add TSS (Thread Specific Storage) API in CPython 3.7+
-rw-r--r-- | Cython/Includes/cpython/pythread.pxd | 14 | ||||
-rw-r--r-- | Cython/Utility/ModuleSetupCode.c | 34 | ||||
-rw-r--r-- | tests/run/tss.pyx | 51 |
3 files changed, 98 insertions, 1 deletions
diff --git a/Cython/Includes/cpython/pythread.pxd b/Cython/Includes/cpython/pythread.pxd index e6c6395e1..8da456743 100644 --- a/Cython/Includes/cpython/pythread.pxd +++ b/Cython/Includes/cpython/pythread.pxd @@ -29,7 +29,7 @@ cdef extern from "pythread.h": size_t PyThread_get_stacksize() int PyThread_set_stacksize(size_t) - # Thread Local Storage (TLS) API + # Thread Local Storage (TLS) API deprecated in CPython 3.7+ int PyThread_create_key() void PyThread_delete_key(int) int PyThread_set_key_value(int, void *) @@ -38,3 +38,15 @@ cdef extern from "pythread.h": # Cleanup after a fork void PyThread_ReInitTLS() + + # Thread Specific Storage (TSS) API in CPython 3.7+ + ctypedef struct Py_tss_t: + pass + Py_tss_t Py_tss_NEEDS_INIT + Py_tss_t * PyThread_tss_alloc() + void PyThread_tss_free(Py_tss_t *key) + int PyThread_tss_is_created(Py_tss_t *key) + int PyThread_tss_create(Py_tss_t *key) + void PyThread_tss_delete(Py_tss_t *key) + int PyThread_tss_set(Py_tss_t *key, void *value) + void * PyThread_tss_get(Py_tss_t *key) diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c index b4e06cabb..7deaa22af 100644 --- a/Cython/Utility/ModuleSetupCode.c +++ b/Cython/Utility/ModuleSetupCode.c @@ -430,6 +430,40 @@ class __Pyx_FakeReference { #define __Pyx_PyThreadState_Current _PyThreadState_Current #endif +// TSS (Thread Specific Storage) API +#if PY_VERSION_HEX < 0x03070000 && !defined(PyThread_tss_create) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; // PyThread_create_key reports success always +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +// PyThread_delete_key_value(key) is equalivalent to PyThread_set_key_value(key, NULL) +// PyThread_ReInitTLS() is a no-op +#endif // TSS (Thread Specific Storage) API + #if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) #define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) #else diff --git a/tests/run/tss.pyx b/tests/run/tss.pyx new file mode 100644 index 000000000..c21b869a6 --- /dev/null +++ b/tests/run/tss.pyx @@ -0,0 +1,51 @@ +# mode: run + +from cpython.pythread cimport * + +def tss_create_delete(): + """ + >>> tss_create_delete() + (True, False) + """ + cdef Py_tss_t tss_key = Py_tss_NEEDS_INIT + cdef bint after_create, after_delete + if PyThread_tss_create(&tss_key) > 0: + # handle key creation failure + pass + after_create = PyThread_tss_is_created(&tss_key) != 0 + PyThread_tss_delete(&tss_key) + after_delete = PyThread_tss_is_created(&tss_key) != 0 + return (after_create, after_delete) + +def tss_alloc_free(): + """ + >>> tss_alloc_free() + (True, False) + """ + cdef Py_tss_t *ptr_key + cdef bint after_alloc, after_free + ptr_key = PyThread_tss_alloc() + if ptr_key == NULL: + # handle key allocation failure + pass + after_alloc = PyThread_tss_is_created(ptr_key) != 0 + PyThread_tss_free(ptr_key) + after_free = PyThread_tss_is_created(ptr_key) != 0 + return (after_alloc, after_free) + +def tss_set_get(): + """ + >>> tss_set_get() + 1 + """ + cdef Py_tss_t tss_key = Py_tss_NEEDS_INIT + cdef int the_value = 1 + cdef int ret_value + if PyThread_tss_create(&tss_key) > 0: + # handle key creation failure + pass + if PyThread_tss_get(&tss_key) == NULL: + PyThread_tss_set(&tss_key, <void *>&the_value) + ret_value = (<int *>PyThread_tss_get(&tss_key))[0] + PyThread_tss_delete(&tss_key) + return ret_value |