Commit 4fc2fd38 authored by Stefan Behnel's avatar Stefan Behnel

Support "@cython.nogil" decorator in pure mode.

Closes #2557.
parent 70b3d15d
......@@ -23,6 +23,9 @@ Features added
* Raising exceptions from nogil code will automatically acquire the GIL, instead
of requiring an explicit ``with gil`` block.
* ``@cython.nogil`` is supported as a C-function decorator in Python code.
(Github issue #2557)
* In CPython 3.6 and later, looking up globals in the module dict is almost
as fast as looking up C globals.
(Github issue #2313)
......
......@@ -2777,7 +2777,8 @@ class DefNode(FuncDefNode):
self.num_required_kw_args = rk
self.num_required_args = r
def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None, except_val=None, modifiers=None):
def as_cfunction(self, cfunc=None, scope=None, overridable=True, returns=None, except_val=None, modifiers=None,
nogil=False, with_gil=False):
if self.star_arg:
error(self.star_arg.pos, "cdef function cannot have star argument")
if self.starstar_arg:
......@@ -2798,8 +2799,8 @@ class DefNode(FuncDefNode):
has_varargs=False,
exception_value=None,
exception_check=exception_check,
nogil=False,
with_gil=False,
nogil=nogil,
with_gil=with_gil,
is_overridable=overridable)
cfunc = CVarDefNode(self.pos, type=cfunc_type)
else:
......
......@@ -184,6 +184,7 @@ _directive_defaults = {
'ccomplex' : False, # use C99/C++ for complex types and arith
'callspec' : "",
'final' : False,
'nogil' : False,
'internal' : False,
'profile': False,
'no_gc_clear': False,
......@@ -323,6 +324,7 @@ directive_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
'auto_pickle': ('module', 'cclass'),
'final' : ('cclass', 'function'),
'nogil' : ('function',),
'inline' : ('function',),
'returns' : ('function',),
'exceptval' : ('function',),
......
......@@ -2333,6 +2333,7 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
@cython.cclass
@cython.ccall
@cython.inline
@cython.nogil
"""
def visit_ModuleNode(self, node):
......@@ -2352,6 +2353,7 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
modifiers = []
if 'inline' in self.directives:
modifiers.append('inline')
nogil = self.directives.get('nogil')
except_val = self.directives.get('exceptval')
return_type_node = self.directives.get('returns')
if return_type_node is None and self.directives['annotation_typing']:
......@@ -2364,7 +2366,7 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
except_val = (None, False)
if 'ccall' in self.directives:
node = node.as_cfunction(
overridable=True, modifiers=modifiers,
overridable=True, modifiers=modifiers, nogil=nogil,
returns=return_type_node, except_val=except_val)
return self.visit(node)
if 'cfunc' in self.directives:
......@@ -2372,11 +2374,14 @@ class AdjustDefByDirectives(CythonTransform, SkipDeclarations):
error(node.pos, "cfunc directive is not allowed here")
else:
node = node.as_cfunction(
overridable=False, modifiers=modifiers,
overridable=False, modifiers=modifiers, nogil=nogil,
returns=return_type_node, except_val=except_val)
return self.visit(node)
if 'inline' in modifiers:
error(node.pos, "Python functions cannot be declared 'inline'")
if nogil:
# TODO: turn this into a "with gil" declaration.
error(node.pos, "Python functions cannot be declared 'nogil'")
self.visitchildren(node)
return node
......
......@@ -123,6 +123,8 @@ overflowcheck.fold = optimization.use_switch = \
final = internal = type_version_tag = no_gc_clear = no_gc = _empty_decorator
gil = nogil = _EmptyDecoratorAndManager()
_cython_inline = None
def inline(f, *args, **kwds):
......@@ -185,17 +187,6 @@ def declare(type=None, value=_Unspecified, **kwds):
else:
return value
class _nogil(object):
"""Support for 'with nogil' statement
"""
def __enter__(self):
pass
def __exit__(self, exc_class, exc, tb):
return exc_class is None
nogil = _nogil()
gil = _nogil()
del _nogil
# Emulated types
......
# mode: error
# tag: warnings
import cython
@cython.cfunc
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_needs_gil(x):
return x + 1
@cython.cfunc
@cython.nogil
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_nogil(x):
return x + 1
@cython.locals(x=cython.int)
def test_cdef_nogil(x):
cdef_nogil(x) # ok
with cython.nogil:
cdef_needs_gil(x) # not ok
@cython.nogil
def pyfunc(x):
return x + 1
_ERRORS = """
25:22: Calling gil-requiring function not allowed without gil
29:0: Python functions cannot be declared 'nogil'
"""
......@@ -267,6 +267,25 @@ def call_cdef_inline(x):
return ret, cython.typeof(ret)
@cython.cfunc
@cython.nogil
@cython.locals(x=cython.int)
@cython.returns(cython.int)
def cdef_nogil(x):
return x + 1
@cython.locals(x=cython.int)
def test_cdef_nogil(x):
"""
>>> test_cdef_nogil(5)
6
"""
with cython.nogil:
result = cdef_nogil(x)
return result
@cython.locals(counts=cython.int[10], digit=cython.int)
def count_digits_in_carray(digits):
"""
......
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