Commit 8fab3aab authored by Stefan Behnel's avatar Stefan Behnel

Promote the new opaque PEP-539 type "Py_tss_t" to a known Cython type to avoid...

Promote the new opaque PEP-539 type "Py_tss_t" to a known Cython type to avoid static variable initialisation issues with the "Py_tss_NEEDS_INIT" struct initialiser value.
parent d9672974
......@@ -27,6 +27,10 @@ Features added
* The new TSS C-API in CPython 3.7 is supported and has been backported.
Patch by Naotoshi Seo. (Github issue #1932)
* Cython knows the new ``Py_tss_t`` type defined in PEP-539 and automatically
initialises variables declared with that type to ``Py_tss_NEEDS_INIT``,
a value which cannot be used outside of static assignments.
* The set methods ``.remove()`` and ``.discard()`` are optimised.
Patch by Antoine Pitrou. (Github issue #2042)
......
......@@ -2710,6 +2710,7 @@ special_basic_c_types = cython.declare(dict, {
"ssize_t" : (2, 0),
"size_t" : (0, 0),
"ptrdiff_t" : (2, 0),
"Py_tss_t" : (1, 0),
})
sign_and_longness_words = cython.declare(
......
......@@ -192,7 +192,8 @@ class PyrexType(BaseType):
# is_pythran_expr boolean Is Pythran expr
# is_numpy_buffer boolean Is Numpy array buffer
# has_attributes boolean Has C dot-selectable attributes
# default_value string Initial value
# default_value string Initial value that can be assigned before first user assignment.
# declaration_value string The value statically assigned on declaration (if any).
# entry Entry The Entry for this type
#
# declaration_code(entity_code,
......@@ -254,6 +255,7 @@ class PyrexType(BaseType):
is_numpy_buffer = 0
has_attributes = 0
default_value = ""
declaration_value = ""
def resolve(self):
# If a typedef, returns the base type.
......@@ -1083,6 +1085,7 @@ class PyObjectType(PyrexType):
name = "object"
is_pyobject = 1
default_value = "0"
declaration_value = "0"
buffer_defaults = None
is_extern = False
is_subclassed = False
......@@ -2226,6 +2229,25 @@ complex_ops = {
}
class CPyTSSTType(CType):
#
# PEP-539 "Py_tss_t" type
#
declaration_value = "Py_tss_NEEDS_INIT"
def __repr__(self):
return "<Py_tss_t>"
def declaration_code(self, entity_code,
for_display=0, dll_linkage=None, pyrex=0):
if pyrex or for_display:
base_code = "Py_tss_t"
else:
base_code = public_decl("Py_tss_t", dll_linkage)
return self.base_declaration_code(base_code, entity_code)
class CPointerBaseType(CType):
# common base type for pointer/array types
#
......@@ -4088,6 +4110,9 @@ c_gilstate_type = CEnumType("PyGILState_STATE", "PyGILState_STATE", True)
c_threadstate_type = CStructOrUnionType("PyThreadState", "struct", None, 1, "PyThreadState")
c_threadstate_ptr_type = CPtrType(c_threadstate_type)
# PEP-539 "Py_tss_t" type
c_pytss_t_type = CPyTSSTType()
# the Py_buffer type is defined in Builtin.py
c_py_buffer_type = CStructOrUnionType("Py_buffer", "struct", None, 1, "Py_buffer")
c_py_buffer_ptr_type = CPtrType(c_py_buffer_type)
......@@ -4153,6 +4178,7 @@ modifiers_and_name_to_type = {
#
(1, 0, "void"): c_void_type,
(1, 0, "Py_tss_t"): c_pytss_t_type,
(1, 0, "bint"): c_bint_type,
(0, 0, "Py_UNICODE"): c_py_unicode_type,
......
......@@ -1378,8 +1378,8 @@ class ModuleScope(Scope):
api=api, in_pxd=in_pxd, is_cdef=is_cdef)
if is_cdef:
entry.is_cglobal = 1
if entry.type.is_pyobject:
entry.init = "0"
if entry.type.declaration_value:
entry.init = entry.type.declaration_value
self.var_entries.append(entry)
else:
entry.is_pyglobal = 1
......@@ -1710,8 +1710,8 @@ class LocalScope(Scope):
entry = Scope.declare_var(self, name, type, pos,
cname=cname, visibility=visibility,
api=api, in_pxd=in_pxd, is_cdef=is_cdef)
if type.is_pyobject:
entry.init = "0"
if entry.type.declaration_value:
entry.init = entry.type.declaration_value
entry.is_local = 1
entry.in_with_gil_block = self._in_with_gil_block
......
......@@ -39,10 +39,9 @@ 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
# Thread Specific Storage (TSS) API in CPython 3.7+ (also backported)
#ctypedef struct Py_tss_t: pass # Cython built-in type
Py_tss_t Py_tss_NEEDS_INIT # Not normally useful: Cython auto-initialises declared "Py_tss_t" variables.
Py_tss_t * PyThread_tss_alloc()
void PyThread_tss_free(Py_tss_t *key)
int PyThread_tss_is_created(Py_tss_t *key)
......
......@@ -385,7 +385,7 @@ py_complex = typedef(complex, "double complex")
int_types = ['char', 'short', 'Py_UNICODE', 'int', 'Py_UCS4', 'long', 'longlong', 'Py_ssize_t', 'size_t']
float_types = ['longdouble', 'double', 'float']
complex_types = ['longdoublecomplex', 'doublecomplex', 'floatcomplex', 'complex']
other_types = ['bint', 'void']
other_types = ['bint', 'void', 'Py_tss_t']
to_repr = {
'longlong': 'long long',
......@@ -420,13 +420,13 @@ for name in complex_types:
gs[name] = typedef(py_complex, to_repr(name, name))
bint = typedef(bool, "bint")
void = typedef(int, "void")
void = typedef(None, "void")
Py_tss_t = typedef(None, "Py_tss_t")
for t in int_types + float_types + complex_types + other_types:
for i in range(1, 4):
gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i)
void = typedef(None, "void")
NULL = gs['p_void'](0)
# looks like 'gs' has some users out there by now...
......
......@@ -3,16 +3,21 @@
from cpython.pythread cimport *
cdef Py_tss_t *pass_py_tss_t_ptr(Py_tss_t *value):
return value
def tss_create_delete():
"""
>>> tss_create_delete()
(True, False)
"""
cdef Py_tss_t tss_key = Py_tss_NEEDS_INIT
cdef Py_tss_t tss_key
cdef bint after_create, after_delete
if PyThread_tss_create(&tss_key) != 0:
raise MemoryError()
after_create = PyThread_tss_is_created(&tss_key) != 0
assert after_create == PyThread_tss_is_created(pass_py_tss_t_ptr(&tss_key))
PyThread_tss_delete(&tss_key)
after_delete = PyThread_tss_is_created(&tss_key) != 0
return (after_create, after_delete)
......@@ -58,7 +63,7 @@ def tss_set_get():
>>> tss_set_get()
1
"""
cdef Py_tss_t tss_key = Py_tss_NEEDS_INIT
cdef Py_tss_t tss_key
cdef int the_value = 1
cdef int ret_value
if PyThread_tss_create(&tss_key) != 0:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment