Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
83047799
Commit
83047799
authored
Feb 05, 2019
by
gsamain
Committed by
Xavier Thompson
Jun 18, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Gwenael: Remove nogil extension and introduce refcounted cypclass
parent
6521ad76
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
324 additions
and
383 deletions
+324
-383
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+26
-3
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+55
-31
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+15
-16
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+50
-24
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+18
-27
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+57
-213
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+15
-17
Cython/Compiler/UtilNodes.py
Cython/Compiler/UtilNodes.py
+8
-2
Cython/Utility/CyObjects.cpp
Cython/Utility/CyObjects.cpp
+75
-0
Cython/Utility/ObjectHandling.c
Cython/Utility/ObjectHandling.c
+0
-45
nogil_test/nogil_extension.pyx
nogil_test/nogil_extension.pyx
+4
-4
test.pyx
test.pyx
+1
-1
No files found.
Cython/Compiler/Code.py
View file @
83047799
...
...
@@ -2039,7 +2039,7 @@ class CCodeWriter(object):
entry
.
cname
,
dll_linkage
=
dll_linkage
))
if
entry
.
init
is
not
None
:
self
.
put_safe
(
" = %s"
%
entry
.
type
.
literal_code
(
entry
.
init
))
elif
entry
.
type
.
is_pyobject
:
elif
entry
.
type
.
is_pyobject
or
entry
.
type
.
is_cyp_class
:
self
.
put
(
" = NULL"
)
self
.
putln
(
";"
)
...
...
@@ -2050,8 +2050,8 @@ class CCodeWriter(object):
self
.
putln
(
"%s = NULL;"
%
decl
)
elif
type
.
is_memoryviewslice
:
self
.
putln
(
"%s = %s;"
%
(
decl
,
type
.
literal_code
(
type
.
default_value
)))
elif
type
.
is_
struct
and
type
.
is_extension_type
and
type
.
nogil
:
self
.
putln
(
"%s;"
%
decl
)
elif
type
.
is_
cyp_class
:
self
.
putln
(
"%s
= NULL
;"
%
decl
)
else
:
self
.
putln
(
"%s%s;"
%
(
static
and
"static "
or
""
,
decl
))
...
...
@@ -2084,6 +2084,29 @@ class CCodeWriter(object):
return
''
return
'%s '
%
' '
.
join
([
mapper
(
m
,
m
)
for
m
in
modifiers
])
# CyObjects reference counting
def
put_cygotref
(
self
,
cname
):
self
.
putln
(
"Cy_GOTREF(%s);"
%
cname
)
def
put_cygiveref
(
self
,
cname
):
self
.
putln
(
"Cy_GIVEREF(%s);"
%
cname
)
def
put_cyxgiveref
(
self
,
cname
):
self
.
putln
(
"Cy_XGIVEREF(%s);"
%
cname
)
def
put_cyxgotref
(
self
,
cname
):
self
.
putln
(
"Cy_XGOTREF(%s);"
%
cname
)
def
put_cyincref
(
self
,
cname
):
self
.
putln
(
"Cy_INCREF(%s);"
%
cname
)
def
put_cydecref
(
self
,
cname
):
self
.
putln
(
"Cy_DECREF(%s);"
%
cname
)
def
put_cyxdecref
(
self
,
cname
):
self
.
putln
(
"Cy_XDECREF(%s);"
%
cname
)
# Python objects and reference counting
def
entry_as_pyobject
(
self
,
entry
):
...
...
Cython/Compiler/ExprNodes.py
View file @
83047799
...
...
@@ -782,7 +782,10 @@ class ExprNode(Node):
If the result is in a temp, it is already a new reference.
"""
if
not
self
.
result_in_temp
():
code
.
put_incref
(
self
.
result
(),
self
.
ctype
())
if
self
.
type
.
is_cyp_class
and
"NULL"
not
in
self
.
result
():
code
.
put_cyincref
(
self
.
result
())
else
:
code
.
put_incref
(
self
.
result
(),
self
.
ctype
())
def
make_owned_memoryviewslice
(
self
,
code
):
"""
...
...
@@ -824,7 +827,10 @@ class ExprNode(Node):
self
.
generate_subexpr_disposal_code
(
code
)
self
.
free_subexpr_temps
(
code
)
if
self
.
result
():
code
.
put_decref_clear
(
self
.
result
(),
self
.
ctype
(),
if
self
.
type
.
is_cyp_class
:
code
.
put_cyxdecref
(
self
.
result
())
else
:
code
.
put_decref_clear
(
self
.
result
(),
self
.
ctype
(),
have_gil
=
not
self
.
in_nogil_context
)
if
self
.
has_temp_moved
:
code
.
globalstate
.
use_utility_code
(
...
...
@@ -847,6 +853,8 @@ class ExprNode(Node):
self
.
free_subexpr_temps
(
code
)
elif
self
.
type
.
is_pyobject
:
code
.
putln
(
"%s = 0;"
%
self
.
result
())
elif
self
.
type
.
is_cyp_class
:
code
.
putln
(
"%s = 0;"
%
self
.
result
())
elif
self
.
type
.
is_memoryviewslice
:
code
.
putln
(
"%s.memview = NULL;"
%
self
.
result
())
code
.
putln
(
"%s.data = NULL;"
%
self
.
result
())
...
...
@@ -1837,7 +1845,10 @@ class ImagNode(AtomicExprNode):
self
.
result
(),
float
(
self
.
value
),
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
self
.
generate_gotref
(
code
)
if
self
.
type
.
is_cyp_class
:
code
.
put_cygotref
(
self
.
result
())
else
:
self
.
generate_gotref
(
code
)
class
NewExprNode
(
AtomicExprNode
):
...
...
@@ -2319,8 +2330,9 @@ class NameNode(AtomicExprNode):
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
self
.
generate_gotref
(
code
)
elif
entry
.
is_local
and
isinstance
(
entry
.
type
,
PyrexTypes
.
CythonExtensionType
):
pass
elif
entry
.
is_local
and
entry
.
type
.
is_cyp_class
:
code
.
put_cygotref
(
self
.
result
())
#pass
# code.putln(entry.cname)
elif
entry
.
is_local
or
entry
.
in_closure
or
entry
.
from_closure
or
entry
.
type
.
is_memoryviewslice
:
# Raise UnboundLocalError for objects and memoryviewslices
...
...
@@ -2426,6 +2438,10 @@ class NameNode(AtomicExprNode):
assigned
=
False
if
is_external_ref
:
rhs
.
generate_giveref
(
code
)
elif
self
.
type
.
is_cyp_class
:
code
.
put_cyxdecref
(
self
.
result
())
if
isinstance
(
rhs
,
NameNode
):
rhs
.
make_owned_reference
(
code
)
if
not
self
.
type
.
is_memoryviewslice
:
if
not
assigned
:
if
overloaded_assignment
:
...
...
@@ -2537,6 +2553,22 @@ class NameNode(AtomicExprNode):
else
:
code
.
put_decref_clear
(
self
.
result
(),
self
.
ctype
(),
have_gil
=
not
self
.
nogil
)
elif
self
.
entry
.
type
.
is_cyp_class
:
if
not
self
.
cf_is_null
:
if
self
.
cf_maybe_null
and
not
ignore_nonexisting
:
code
.
put_error_if_unbound
(
self
.
pos
,
self
.
entry
)
if
self
.
entry
.
in_closure
:
# generator
if
ignore_nonexisting
and
self
.
cf_maybe_null
:
code
.
put_cyxgotref
(
self
.
result
())
else
:
code
.
put_cygotref
(
self
.
result
())
if
ignore_nonexisting
and
self
.
cf_maybe_null
:
code
.
put_cyxdecref
(
self
.
result
())
else
:
code
.
put_cydecref
(
self
.
result
())
code
.
putln
(
'%s = NULL;'
%
self
.
result
())
else
:
error
(
self
.
pos
,
"Deletion of C names not supported"
)
...
...
@@ -4135,6 +4167,8 @@ class IndexNode(_IndexingBaseNode):
code
.
error_goto_if
(
error_check
%
self
.
result
(),
self
.
pos
)))
if
self
.
type
.
is_pyobject
:
self
.
generate_gotref
(
code
)
elif
self
.
type
.
is_cyp_class
:
code
.
put_cygotref
(
self
.
result
())
def
generate_setitem_code
(
self
,
value_code
,
code
):
if
self
.
index
.
type
.
is_int
:
...
...
@@ -5555,18 +5589,6 @@ class CallNode(ExprNode):
self
.
analyse_c_function_call
(
env
)
self
.
type
=
type
return
True
elif
type
and
type
.
is_struct
and
type
.
nogil
:
args
,
kwds
=
self
.
explicit_args_kwds
()
items
=
[]
for
arg
,
member
in
zip
(
args
,
type
.
scope
.
var_entries
):
items
.
append
(
DictItemNode
(
pos
=
arg
.
pos
,
key
=
StringNode
(
pos
=
arg
.
pos
,
value
=
member
.
name
),
value
=
arg
))
if
kwds
:
items
+=
kwds
.
key_value_pairs
self
.
key_value_pairs
=
items
self
.
__class__
=
DictNode
self
.
analyse_types
(
env
)
# FIXME
self
.
coerce_to
(
type
,
env
)
return
True
def
is_lvalue
(
self
):
return
self
.
type
.
is_reference
...
...
@@ -6069,6 +6091,8 @@ class SimpleCallNode(CallNode):
code
.
putln
(
"%s%s; %s"
%
(
lhs
,
rhs
,
goto_error
))
if
self
.
type
.
is_pyobject
and
self
.
result
():
self
.
generate_gotref
(
code
)
elif
self
.
type
.
is_cyp_class
and
self
.
result
():
code
.
put_cygotref
(
self
.
result
())
if
self
.
has_optional_args
:
code
.
funcstate
.
release_temp
(
self
.
opt_arg_struct
)
...
...
@@ -7073,6 +7097,8 @@ class AttributeNode(ExprNode):
self
.
op
=
"->"
elif
obj_type
.
is_reference
and
obj_type
.
is_fake_reference
:
self
.
op
=
"->"
elif
obj_type
.
is_cyp_class
:
self
.
op
=
"->"
else
:
self
.
op
=
"."
if
obj_type
.
has_attributes
:
...
...
@@ -7223,12 +7249,9 @@ class AttributeNode(ExprNode):
# (AnalyseExpressionsTransform)
self
.
member
=
self
.
entry
.
cname
if
obj
.
type
.
nogil
:
return
"%s"
%
self
.
entry
.
func_cname
else
:
return
"((struct %s *)%s%s%s)->%s"
%
(
obj
.
type
.
vtabstruct_cname
,
obj_code
,
self
.
op
,
obj
.
type
.
vtabslot_cname
,
self
.
member
)
return
"((struct %s *)%s%s%s)->%s"
%
(
obj
.
type
.
vtabstruct_cname
,
obj_code
,
self
.
op
,
obj
.
type
.
vtabslot_cname
,
self
.
member
)
elif
self
.
result_is_used
:
return
self
.
member
# Generating no code at all for unused access to optimised builtin
...
...
@@ -7329,6 +7352,11 @@ class AttributeNode(ExprNode):
from
.
import
MemoryView
MemoryView
.
put_assign_to_memviewslice
(
select_code
,
rhs
,
rhs
.
result
(),
self
.
type
,
code
)
elif
self
.
type
.
is_cyp_class
:
rhs
.
make_owned_reference
(
code
)
code
.
put_cygiveref
(
rhs
.
result
())
code
.
put_cygotref
(
select_code
)
code
.
put_cyxdecref
(
select_code
)
if
not
self
.
type
.
is_memoryviewslice
:
code
.
putln
(
...
...
@@ -8827,8 +8855,6 @@ class DictNode(ExprNode):
# pairs are evaluated and used one at a time.
code
.
mark_pos
(
self
.
pos
)
self
.
allocate_temp_result
(
code
)
if
hasattr
(
self
.
type
,
'nogil'
)
and
self
.
type
.
nogil
:
code
.
putln
(
"%s = (struct %s *)malloc(sizeof(struct %s));"
%
(
self
.
result
(),
self
.
type
.
objstruct_cname
,
self
.
type
.
objstruct_cname
))
is_dict
=
self
.
type
.
is_pyobject
if
is_dict
:
...
...
@@ -8886,11 +8912,6 @@ class DictNode(ExprNode):
code
.
putln
(
'}'
)
if
self
.
exclude_null_values
:
code
.
putln
(
'}'
)
elif
self
.
type
.
nogil
:
code
.
putln
(
"%s->%s = %s;"
%
(
self
.
result
(),
item
.
key
.
value
,
item
.
value
.
result
()))
else
:
code
.
putln
(
"%s.%s = %s;"
%
(
self
.
result
(),
...
...
@@ -13519,7 +13540,10 @@ class CoerceToTempNode(CoercionNode):
self
.
result
(),
self
.
arg
.
result_as
(
self
.
ctype
())))
if
self
.
use_managed_ref
:
if
not
self
.
type
.
is_memoryviewslice
:
code
.
put_incref
(
self
.
result
(),
self
.
ctype
())
if
self
.
type
.
is_cyp_class
:
code
.
put_cyincref
(
self
.
result
())
else
:
code
.
put_incref
(
self
.
result
(),
self
.
ctype
())
else
:
code
.
put_incref_memoryviewslice
(
self
.
result
(),
self
.
type
,
have_gil
=
not
self
.
in_nogil_context
)
...
...
Cython/Compiler/ModuleNode.py
View file @
83047799
...
...
@@ -6,7 +6,7 @@ from __future__ import absolute_import
import
cython
cython
.
declare
(
Naming
=
object
,
Options
=
object
,
PyrexTypes
=
object
,
TypeSlots
=
object
,
error
=
object
,
warning
=
object
,
py_object_type
=
object
,
UtilityCode
=
object
,
error
=
object
,
warning
=
object
,
py_object_type
=
object
,
cy_object_type
=
object
,
UtilityCode
=
object
,
EncodedString
=
object
,
re
=
object
)
from
collections
import
defaultdict
...
...
@@ -28,7 +28,7 @@ from . import PyrexTypes
from
.
import
Pythran
from
.Errors
import
error
,
warning
from
.PyrexTypes
import
py_object_type
from
.PyrexTypes
import
py_object_type
,
cy_object_type
from
..Utils
import
open_new_file
,
replace_suffix
,
decode_filename
,
build_hex_version
from
.Code
import
UtilityCode
,
IncludeCode
from
.StringEncoding
import
EncodedString
,
encoded_string_or_bytes_literal
...
...
@@ -980,17 +980,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# Just let everything be public.
code
.
put
(
"struct %s"
%
type
.
cname
)
if
type
.
base_classes
:
base_class_decl
=
", public "
.
join
(
[
base_class
.
empty_declaration_code
()
for
base_class
in
type
.
base_classes
])
base_class_list
=
[
base_class
.
empty_declaration_code
()
for
base_class
in
type
.
base_classes
]
if
type
.
is_cyp_class
and
type
.
base_classes
[
-
1
]
is
cy_object_type
:
base_class_list
[
-
1
]
=
"virtual "
+
base_class_list
[
-
1
]
base_class_decl
=
", public "
.
join
(
base_class_list
)
code
.
put
(
" : public %s"
%
base_class_decl
)
code
.
putln
(
" {"
)
self
.
generate_type_header_code
(
scope
.
type_entries
,
code
)
self
.
generate_cyp_class_wrapper_definitions
(
scope
.
sue_entries
,
code
)
py_attrs
=
[
e
for
e
in
scope
.
entries
.
values
()
if
e
.
type
.
is_pyobject
and
not
e
.
is_inherited
]
has_virtual_methods
=
False
constructor
=
None
destructor
=
None
for
attr
in
scope
.
var_entries
:
cname
=
attr
.
cname
if
attr
.
type
.
is_cfunction
and
attr
.
type
.
is_static_method
:
code
.
put
(
"static "
)
elif
attr
.
name
==
"<init>"
:
...
...
@@ -1001,7 +1005,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
elif
attr
.
type
.
is_cfunction
:
code
.
put
(
"virtual "
)
has_virtual_methods
=
True
code
.
putln
(
"%s;"
%
attr
.
type
.
declaration_code
(
attr
.
cname
))
elif
attr
.
type
.
is_cyp_class
:
cname
=
"%s = NULL"
%
cname
code
.
putln
(
"%s;"
%
attr
.
type
.
declaration_code
(
cname
))
is_implementing
=
'init_module'
in
code
.
globalstate
.
parts
def
generate_cpp_constructor_code
(
arg_decls
,
arg_names
,
is_implementing
,
py_attrs
,
constructor
):
...
...
@@ -1084,6 +1090,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"%s& operator=(const %s& __Pyx_other);"
%
(
type
.
cname
,
type
.
cname
))
code
.
putln
(
"};"
)
if
type
.
is_cyp_class
:
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load
(
"CyObjects"
,
"CyObjects.cpp"
,
proto_block
=
"utility_code_proto_before_types"
))
def
generate_enum_definition
(
self
,
entry
,
code
):
code
.
mark_pos
(
entry
.
pos
)
type
=
entry
.
type
...
...
@@ -1197,7 +1207,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self
.
sue_header_footer
(
type
,
"struct"
,
type
.
objstruct_cname
)
code
.
putln
(
header
)
base_type
=
type
.
base_type
nogil
=
type
.
nogil
if
base_type
:
basestruct_cname
=
base_type
.
objstruct_cname
if
basestruct_cname
==
"PyTypeObject"
:
...
...
@@ -1208,16 +1217,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
(
"struct "
,
""
)[
base_type
.
typedef_flag
],
basestruct_cname
,
Naming
.
obj_base_cname
))
elif
nogil
:
# Extension type with nogil keyword indicate it is a CPython-free struct
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CythonReferenceCounting"
,
"ObjectHandling.c"
))
code
.
putln
(
"// nogil"
)
code
.
putln
(
"int ob_refcnt;"
# "CyObject_HEAD;" Sometimes the CythonReferenceCounting was put after the nogil extension declaration, WTF!!!
)
else
:
code
.
putln
(
"PyObject_HEAD"
)
...
...
Cython/Compiler/Nodes.py
View file @
83047799
This diff is collapsed.
Click to expand it.
Cython/Compiler/Parsing.py
View file @
83047799
...
...
@@ -2235,7 +2235,7 @@ def p_statement(s, ctx, first_statement = 0):
elif
s
.
sy
==
'IF'
:
return
p_IF_statement
(
s
,
ctx
)
elif
s
.
sy
==
'@'
:
if
ctx
.
level
not
in
(
'module'
,
'class'
,
'c_class'
,
'
class_nogil'
,
'
function'
,
'property'
,
'module_pxd'
,
'c_class_pxd'
,
'other'
):
if
ctx
.
level
not
in
(
'module'
,
'class'
,
'c_class'
,
'function'
,
'property'
,
'module_pxd'
,
'c_class_pxd'
,
'other'
):
s
.
error
(
'decorator not allowed here'
)
s
.
level
=
ctx
.
level
decorators
=
p_decorators
(
s
)
...
...
@@ -2249,21 +2249,20 @@ def p_statement(s, ctx, first_statement = 0):
return
p_pass_statement
(
s
,
with_newline
=
1
)
overridable
=
0
nogil_flag
=
ctx
.
nogil
if
s
.
sy
==
'cdef'
:
cdef_flag
=
1
s
.
next
()
elif
s
.
sy
==
'cpdef'
:
if
ctx
.
level
==
'c_class_nogil'
:
s
.
error
(
'cpdef statement not allowed in nogil extension type'
)
s
.
level
=
ctx
.
level
cdef_flag
=
1
overridable
=
1
s
.
next
()
if
cdef_flag
:
if
ctx
.
level
not
in
(
'module'
,
'module_pxd'
,
'function'
,
'c_class'
,
'c_class_
nogil'
,
'c_class_
pxd'
):
if
ctx
.
level
not
in
(
'module'
,
'module_pxd'
,
'function'
,
'c_class'
,
'c_class_pxd'
):
s
.
error
(
'cdef statement not allowed here'
)
s
.
level
=
ctx
.
level
node
=
p_cdef_statement
(
s
,
ctx
(
overridable
=
overridable
))
node
=
p_cdef_statement
(
s
,
ctx
(
overridable
=
overridable
,
nogil
=
nogil_flag
))
if
decorators
is
not
None
:
tup
=
(
Nodes
.
CFuncDefNode
,
Nodes
.
CVarDefNode
,
Nodes
.
CClassDefNode
)
if
ctx
.
allow_struct_enum_decorator
:
...
...
@@ -2280,8 +2279,6 @@ def p_statement(s, ctx, first_statement = 0):
# as part of a cdef class
if
(
'pxd'
in
ctx
.
level
)
and
(
ctx
.
level
!=
'c_class_pxd'
):
s
.
error
(
'def statement not allowed here'
)
if
ctx
.
level
==
'c_class_nogil'
:
s
.
error
(
'def statement not allowed in nogil extension type, only cdef with nogil is allowed'
)
s
.
level
=
ctx
.
level
return
p_def_statement
(
s
,
decorators
)
elif
s
.
sy
==
'class'
:
...
...
@@ -2292,7 +2289,7 @@ def p_statement(s, ctx, first_statement = 0):
if
ctx
.
level
not
in
(
'module'
,
'module_pxd'
):
s
.
error
(
"include statement not allowed here"
)
return
p_include_statement
(
s
,
ctx
)
elif
ctx
.
level
in
(
'c_class'
,
'c_class_nogil'
)
and
s
.
sy
==
'IDENT'
and
s
.
systring
==
'property'
:
elif
ctx
.
level
==
'c_class'
and
s
.
sy
==
'IDENT'
and
s
.
systring
==
'property'
:
return
p_property_decl
(
s
)
elif
s
.
sy
==
'pass'
and
ctx
.
level
!=
'property'
:
return
p_pass_statement
(
s
,
with_newline
=
True
)
...
...
@@ -3068,9 +3065,11 @@ def p_cdef_statement(s, ctx):
return
p_cdef_extern_block
(
s
,
pos
,
ctx
)
elif
p_nogil
(
s
):
ctx
.
nogil
=
1
if
ctx
.
overridable
:
error
(
pos
,
"cdef blocks cannot be declared cpdef"
)
#
if ctx.overridable:
#
error(pos, "cdef blocks cannot be declared cpdef")
return
p_cdef_block
(
s
,
ctx
)
elif
ctx
.
overridable
and
ctx
.
nogil
:
error
(
pos
,
"nogil blocks cannot be declared cpdef"
)
elif
s
.
sy
==
':'
:
if
ctx
.
overridable
:
error
(
pos
,
"cdef blocks cannot be declared cpdef"
)
...
...
@@ -3081,7 +3080,7 @@ def p_cdef_statement(s, ctx):
if
ctx
.
overridable
:
error
(
pos
,
"Extension types cannot be declared cpdef"
)
return
p_c_class_definition
(
s
,
pos
,
ctx
)
elif
s
.
sy
==
'IDENT'
and
s
.
systring
==
'cppclass'
:
elif
s
.
sy
==
'IDENT'
and
s
.
systring
in
(
'cppclass'
,
'cypclass'
)
:
return
p_cpp_class_definition
(
s
,
pos
,
ctx
)
elif
s
.
sy
==
'IDENT'
and
s
.
systring
in
struct_enum_union
:
if
ctx
.
level
not
in
(
'module'
,
'module_pxd'
):
...
...
@@ -3276,7 +3275,7 @@ def p_c_modifiers(s):
return
[]
def
p_c_func_or_var_declaration
(
s
,
pos
,
ctx
):
cmethod_flag
=
ctx
.
level
in
(
'c_class'
,
'c_class_pxd'
,
'c_class_nogil'
)
cmethod_flag
=
ctx
.
level
in
(
'c_class'
,
'c_class_pxd'
)
modifiers
=
p_c_modifiers
(
s
)
base_type
=
p_c_base_type
(
s
,
nonempty
=
1
,
templates
=
ctx
.
templates
)
declarator
=
p_c_declarator
(
s
,
ctx
(
modifiers
=
modifiers
),
cmethod_flag
=
cmethod_flag
,
...
...
@@ -3295,13 +3294,8 @@ def p_c_func_or_var_declaration(s, pos, ctx):
fatal
=
False
)
s
.
next
()
p_test
(
s
)
# Keep going, but ignore result.
if
s
.
sy
==
'nogil'
:
nogil
=
p_nogil
(
s
)
s
.
next
()
if
ctx
.
level
==
'c_class_nogil'
and
not
nogil
:
s
.
error
(
"Only C function with nogil allowed in nogil extension"
)
if
s
.
sy
==
':'
:
if
ctx
.
level
not
in
(
'module'
,
'c_class'
,
'module_pxd'
,
'c_class_pxd'
,
'cpp_class'
,
'c_class_nogil'
)
and
not
ctx
.
templates
:
if
ctx
.
level
not
in
(
'module'
,
'c_class'
,
'module_pxd'
,
'c_class_pxd'
,
'cpp_class'
)
and
not
ctx
.
templates
:
s
.
error
(
"C function definition not allowed here"
)
doc
,
suite
=
p_suite_with_docstring
(
s
,
Ctx
(
level
=
'function'
))
result
=
Nodes
.
CFuncDefNode
(
pos
,
...
...
@@ -3329,7 +3323,7 @@ def p_c_func_or_var_declaration(s, pos, ctx):
declarators
.
append
(
declarator
)
doc_line
=
s
.
start_line
+
1
s
.
expect_newline
(
"Syntax error in C variable declaration"
,
ignore_semicolon
=
True
)
if
ctx
.
level
in
(
'c_class'
,
'c_class_pxd'
,
'c_class_nogil'
)
and
s
.
start_line
==
doc_line
:
if
ctx
.
level
in
(
'c_class'
,
'c_class_pxd'
)
and
s
.
start_line
==
doc_line
:
doc
=
p_doc_string
(
s
)
else
:
doc
=
None
...
...
@@ -3530,12 +3524,9 @@ def p_c_class_definition(s, pos, ctx):
if
ctx
.
visibility
not
in
(
'public'
,
'extern'
)
and
not
ctx
.
api
:
error
(
s
.
position
(),
"Name options only allowed for 'public', 'api', or 'extern' C class"
)
objstruct_name
,
typeobj_name
,
check_size
=
p_c_class_options
(
s
)
nogil
=
p_nogil
(
s
)
if
s
.
sy
==
':'
:
if
ctx
.
level
==
'module_pxd'
:
body_level
=
'c_class_pxd'
elif
nogil
:
body_level
=
'c_class_nogil'
else
:
body_level
=
'c_class'
doc
,
body
=
p_suite_with_docstring
(
s
,
Ctx
(
level
=
body_level
))
...
...
@@ -3574,8 +3565,7 @@ def p_c_class_definition(s, pos, ctx):
check_size
=
check_size
,
in_pxd
=
ctx
.
level
==
'module_pxd'
,
doc
=
doc
,
body
=
body
,
nogil
=
nogil
or
ctx
.
nogil
)
body
=
body
)
def
p_c_class_options
(
s
):
...
...
@@ -3756,7 +3746,8 @@ def p_template_definition(s):
return
name
,
required
def
p_cpp_class_definition
(
s
,
pos
,
ctx
):
# s.sy == 'cppclass'
# s.sy in ('cppclass', 'cypclass')
cypclass
=
s
.
systring
==
'cypclass'
s
.
next
()
module_path
=
[]
class_name
=
p_ident
(
s
)
...
...
@@ -3787,7 +3778,7 @@ def p_cpp_class_definition(s, pos, ctx):
base_classes
=
[]
if
s
.
sy
==
'['
:
error
(
s
.
position
(),
"Name options not allowed for C++ class"
)
nogil
=
p_nogil
(
s
)
nogil
=
p_nogil
(
s
)
or
cypclass
if
s
.
sy
==
':'
:
s
.
next
()
s
.
expect
(
'NEWLINE'
)
...
...
@@ -3816,7 +3807,7 @@ def p_cpp_class_definition(s, pos, ctx):
visibility
=
ctx
.
visibility
,
in_pxd
=
ctx
.
level
==
'module_pxd'
,
attributes
=
attributes
,
templates
=
templates
)
templates
=
templates
,
cypclass
=
cypclass
)
def
p_cpp_class_attribute
(
s
,
ctx
):
decorators
=
None
...
...
Cython/Compiler/PyrexTypes.py
View file @
83047799
This diff is collapsed.
Click to expand it.
Cython/Compiler/Symtab.py
View file @
83047799
...
...
@@ -17,7 +17,7 @@ from .Errors import warning, error, InternalError
from
.StringEncoding
import
EncodedString
from
.
import
Options
,
Naming
from
.
import
PyrexTypes
from
.PyrexTypes
import
py_object_type
,
unspecified_type
from
.PyrexTypes
import
py_object_type
,
cy_object_type
,
unspecified_type
from
.TypeSlots
import
(
pyfunction_signature
,
pymethod_signature
,
richcmp_special_methods
,
get_special_method_signature
,
get_property_accessor_signature
)
...
...
@@ -628,7 +628,7 @@ class Scope(object):
def
declare_cpp_class
(
self
,
name
,
scope
,
pos
,
cname
=
None
,
base_classes
=
(),
visibility
=
'extern'
,
templates
=
None
):
visibility
=
'extern'
,
templates
=
None
,
cypclass
=
0
):
if
cname
is
None
:
if
self
.
in_cinclude
or
(
visibility
!=
'private'
):
cname
=
name
...
...
@@ -637,8 +637,12 @@ class Scope(object):
base_classes
=
list
(
base_classes
)
entry
=
self
.
lookup_here
(
name
)
if
not
entry
:
type
=
PyrexTypes
.
CppClassType
(
name
,
scope
,
cname
,
base_classes
,
templates
=
templates
)
if
cypclass
:
type
=
PyrexTypes
.
CypClassType
(
name
,
scope
,
cname
,
base_classes
,
templates
=
templates
)
else
:
type
=
PyrexTypes
.
CppClassType
(
name
,
scope
,
cname
,
base_classes
,
templates
=
templates
)
entry
=
self
.
declare_type
(
name
,
type
,
pos
,
cname
,
visibility
=
visibility
,
defining
=
scope
is
not
None
)
self
.
sue_entries
.
append
(
entry
)
...
...
@@ -666,7 +670,7 @@ class Scope(object):
def
declare_inherited_attributes
(
entry
,
base_classes
):
for
base_class
in
base_classes
:
if
base_class
is
PyrexTypes
.
error_type
:
if
base_class
is
PyrexTypes
.
error_type
or
base_class
is
PyrexTypes
.
cy_object_type
:
continue
if
base_class
.
scope
is
None
:
error
(
pos
,
"Cannot inherit from incomplete type"
)
...
...
@@ -1573,7 +1577,7 @@ class ModuleScope(Scope):
def
declare_c_class
(
self
,
name
,
pos
,
defining
=
0
,
implementing
=
0
,
module_name
=
None
,
base_type
=
None
,
objstruct_cname
=
None
,
typeobj_cname
=
None
,
typeptr_cname
=
None
,
visibility
=
'private'
,
typedef_flag
=
0
,
api
=
0
,
nogil
=
0
,
check_size
=
None
,
typedef_flag
=
0
,
api
=
0
,
check_size
=
None
,
buffer_defaults
=
None
,
shadow
=
0
):
# If this is a non-extern typedef class, expose the typedef, but use
# the non-typedef struct internally to avoid needing forward
...
...
@@ -1606,15 +1610,8 @@ class ModuleScope(Scope):
# Make a new entry if needed
#
if
not
entry
or
shadow
:
if
nogil
:
pass
if
nogil
:
type
=
PyrexTypes
.
CythonExtensionType
(
name
,
typedef_flag
,
base_type
,
visibility
==
'extern'
,
check_size
=
check_size
)
else
:
type
=
PyrexTypes
.
PyExtensionType
(
name
,
typedef_flag
,
base_type
,
visibility
==
'extern'
,
check_size
=
check_size
)
type
.
nogil
=
nogil
type
=
PyrexTypes
.
PyExtensionType
(
name
,
typedef_flag
,
base_type
,
visibility
==
'extern'
,
check_size
=
check_size
)
type
.
pos
=
pos
type
.
buffer_defaults
=
buffer_defaults
if
objtypedef_cname
is
not
None
:
...
...
@@ -2334,8 +2331,7 @@ class CClassScope(ClassScope):
defining
=
0
,
modifiers
=
(),
utility_code
=
None
,
overridable
=
False
):
name
=
self
.
mangle_class_private_name
(
name
)
if
get_special_method_signature
(
name
)
and
not
self
.
parent_type
.
is_builtin_type
:
if
not
(
hasattr
(
self
.
parent_type
,
"nogil"
)
and
self
.
parent_type
.
nogil
and
self
.
parent_type
.
is_struct_or_union
):
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
error
(
pos
,
"Special methods must be declared with 'def', not 'cdef'"
)
args
=
type
.
args
if
not
type
.
is_static_method
:
if
not
args
:
...
...
@@ -2571,6 +2567,8 @@ class CppClassScope(Scope):
type
.
return_type
=
PyrexTypes
.
c_void_type
if
name
in
(
'<init>'
,
'<del>'
)
and
type
.
nogil
:
for
base
in
self
.
type
.
base_classes
:
if
base
is
cy_object_type
:
continue
base_entry
=
base
.
scope
.
lookup
(
name
)
if
base_entry
and
not
base_entry
.
type
.
nogil
:
error
(
pos
,
"Constructor cannot be called without GIL unless all base constructors can also be called without GIL"
)
...
...
Cython/Compiler/UtilNodes.py
View file @
83047799
...
...
@@ -198,10 +198,13 @@ class ResultRefNode(AtomicExprNode):
pass
def
generate_assignment_code
(
self
,
rhs
,
code
,
overloaded_assignment
=
False
):
if
self
.
type
.
is_pyobject
:
if
self
.
type
.
is_pyobject
or
self
.
type
.
is_cyp_class
:
rhs
.
make_owned_reference
(
code
)
if
not
self
.
lhs_of_first_assignment
:
code
.
put_decref
(
self
.
result
(),
self
.
ctype
())
if
self
.
type
.
is_pyobject
:
code
.
put_decref
(
self
.
result
(),
self
.
ctype
())
elif
self
.
type
.
is_cyp_class
:
code
.
put_cydecref
(
self
.
result
())
code
.
putln
(
'%s = %s;'
%
(
self
.
result
(),
rhs
.
result
()
if
overloaded_assignment
else
rhs
.
result_as
(
self
.
ctype
()),
...
...
@@ -248,6 +251,9 @@ class LetNodeMixin:
else
:
if
self
.
temp_type
.
is_pyobject
:
code
.
put_decref_clear
(
self
.
temp
,
self
.
temp_type
)
elif
self
.
temp_type
.
is_cyp_class
:
pass
#code.put_decref_clear(self.temp, self.temp_type)
code
.
funcstate
.
release_temp
(
self
.
temp
)
...
...
Cython/Utility/CyObjects.cpp
0 → 100644
View file @
83047799
/////////////// CyObjects.proto ///////////////
#if !defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
/* Test for GCC > 4.9.0 */
#if GCC_VERSION < 40900
#error atomic.h works only with GCC newer than version 4.9
#endif
/* GNUC >= 4.9 */
#endif
/* Has GCC */
#ifdef __cplusplus
#if __cplusplus >= 201103L
#include <atomic>
using
namespace
std
;
#define CyObject_ATOMIC_REFCOUNT_TYPE atomic_int
class
CyObject
{
private:
CyObject_ATOMIC_REFCOUNT_TYPE
ob_refcnt
;
public:
CyObject
()
:
ob_refcnt
(
1
)
{}
virtual
~
CyObject
()
{}
void
CyObject_INCREF
();
int
CyObject_DECREF
();
};
static
inline
int
_Cy_DECREF
(
CyObject
*
op
)
{
return
op
->
CyObject_DECREF
();
}
static
inline
void
_Cy_INCREF
(
CyObject
*
op
)
{
op
->
CyObject_INCREF
();
}
/* Cast argument to CyObject* type. */
#define _CyObject_CAST(op) op
#define Cy_INCREF(op) do {if (op != NULL) {_Cy_INCREF(_CyObject_CAST(op));}} while(0)
#define Cy_DECREF(op) do {if (_Cy_DECREF(_CyObject_CAST(op))) {op = NULL;}} while(0)
#define Cy_XDECREF(op) do {if (op != NULL) {Cy_DECREF(op);}} while(0)
#define Cy_GOTREF(op)
#define Cy_XGOTREF(op)
#define Cy_GIVEREF(op)
#define Cy_XGIVEREF(op)
#endif
#endif
/////////////// CyObjects ///////////////
#ifdef __cplusplus
#include <cstdlib>
#include <cstddef>
// atomic is already included in ModuleSetupCode
// #include <atomic>
#else
#error C++ needed for cython+ nogil classes
#endif
/* __cplusplus */
void
CyObject
::
CyObject_INCREF
()
{
atomic_fetch_add
(
&
(
this
->
ob_refcnt
),
1
);
}
int
CyObject
::
CyObject_DECREF
()
{
if
(
atomic_fetch_sub
(
&
(
this
->
ob_refcnt
),
1
)
==
1
)
{
delete
this
;
return
1
;
}
return
0
;
}
Cython/Utility/ObjectHandling.c
View file @
83047799
...
...
@@ -1851,51 +1851,6 @@ try_unpack:
return
0
;
}
/////////////// CythonReferenceCounting.proto ///////////////
#include <stdlib.h>
#include <stddef.h>
#if !defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
/* Test for GCC > 4.9.0 */
#if GCC_VERSION < 40900
#error atomic.h works only with GCC newer than version 4.9
#endif
/* GNUC >= 4.9 */
#endif
/* Has GCC */
// #include <stdatomic.h>
/* CyObject_HEAD defines the initial segment of every CyObject. */
#define CyObject_HEAD \
int ob_refcnt; \
void (*cdealloc)();
struct
CyObject
{
CyObject_HEAD
};
/* Cast argument to PyObject* type. */
#define _CyObject_CAST(op) ((struct CyObject*)(op))
// XXX: Without scope analysis this is useless...
/*
static inline void _Cy_DECREF(struct CyObject *op) {
if (atomic_fetch_sub(&(op->ob_refcnt), 1) == 1) {
op->cdealloc(op);
}
}
static inline void _Cy_INCREF(struct CyObject *op) {
atomic_fetch_add(&(op->ob_refcnt), 1);
}
#define Cy_INCREF(op) _Cy_INCREF(_CyObject_CAST(op))
#define Cy_DECREF(op) _Cy_DECREF(_CyObject_CAST(op))
*/
/////////////// UnpackUnboundCMethod.proto ///////////////
...
...
nogil_test/nogil_extension.pyx
View file @
83047799
...
...
@@ -32,7 +32,7 @@ from libc.stdio cimport printf
# cdef class SomeMemory:
c
def
class
SomeMemory
nogil
:
c
cdef
class
SomeMemory
:
"""
This is a cdef class which is also called
a extensino type. It is a kind of C struct
...
...
@@ -41,7 +41,7 @@ cdef class SomeMemory nogil:
We would like to be able to define "nogil"
extension types:
c
def class SomeMemory nogil
:
c
cdef class SomeMemory
:
where all methods are "nogil" and memory
allocation does not depend on python runtime
...
...
@@ -54,10 +54,10 @@ cdef class SomeMemory nogil:
# self.b = b
pass
cdef
void
cdealloc
(
self
)
nogil
:
cdef
void
cdealloc
(
self
):
pass
cdef
void
foo1
(
self
)
nogil
:
cdef
void
foo1
(
self
):
"""
It is possible to define native C/Cython methods
that release the GIL (cool...)
...
...
test.pyx
View file @
83047799
...
...
@@ -31,7 +31,7 @@ from libc.stdio cimport printf
# cdef class SomeMemory:
c
def
class
SomeMemory
nogil
:
c
cdef
class
SomeMemory
:
"""
This is a cdef class which is also called
a extensino type. It is a kind of C struct
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment