Commit b356ac87 authored by Stefan Behnel's avatar Stefan Behnel

support automatic GIL grabbing inside a function by addign 'withGIL' to its signature

parent e82f5b5c
......@@ -284,6 +284,13 @@ class CCodeWriter:
# code = "((PyObject*)%s)" % code
self.put_init_to_py_none(code, entry.type)
def put_py_gil_state_ensure(self, cname):
self.putln("PyGILState_STATE %s;" % cname)
self.putln("%s = PyGILState_Ensure();" % cname)
def put_py_gil_state_release(self, cname):
self.putln("PyGILState_Release(%s);" % cname)
def put_pymethoddef(self, entry, term):
if entry.doc:
doc_code = entry.doc_cname
......
......@@ -53,5 +53,6 @@ self_cname = pyrex_prefix + "self"
stringtab_cname = pyrex_prefix + "string_tab"
vtabslot_cname = pyrex_prefix + "vtab"
c_api_tab_cname = pyrex_prefix + "c_api_tab"
gilstate_cname = pyrex_prefix + "state"
extern_c_macro = pyrex_prefix.upper() + "EXTERN_C"
......@@ -282,6 +282,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
# has_varargs boolean
# exception_value ConstNode
# exception_check boolean True if PyErr_Occurred check needed
# with_gil boolean True if GIL should be grabbed/released
def analyse(self, return_type, env):
func_type_args = []
......@@ -317,7 +318,8 @@ class CFuncDeclaratorNode(CDeclaratorNode):
exc_check = self.exception_check
func_type = PyrexTypes.CFuncType(
return_type, func_type_args, self.has_varargs,
exception_value = exc_val, exception_check = exc_check)
exception_value = exc_val, exception_check = exc_check,
with_gil = self.with_gil)
return self.base.analyse(func_type, env)
......@@ -572,6 +574,8 @@ class FuncDefNode(StatNode, BlockNode):
self.generate_keyword_list(code)
# ----- Extern library function declarations
lenv.generate_library_function_declarations(code)
# ----- Grab GIL
self.generate_grab_gil(code)
# ----- Fetch arguments
self.generate_argument_parsing_code(code)
self.generate_argument_increfs(lenv, code)
......@@ -623,6 +627,9 @@ class FuncDefNode(StatNode, BlockNode):
code.put_var_decrefs(lenv.var_entries, used_only = 1)
code.put_var_decrefs(lenv.arg_entries)
self.put_stararg_decrefs(code)
# ----- Release GIL
self.generate_release_gil(code)
# ----- Return
if not self.return_type.is_void:
retval_code = Naming.retval_cname
#if self.return_type.is_extension_type:
......@@ -653,6 +660,12 @@ class FuncDefNode(StatNode, BlockNode):
def generate_execution_code(self, code):
pass
def generate_grab_gil(self, code):
pass
def generate_release_gil(self, code):
pass
class CFuncDefNode(FuncDefNode):
# C function definition.
......@@ -757,6 +770,18 @@ class CFuncDefNode(FuncDefNode):
error(arg.pos, "Cannot test type of extern C class "
"without type object name specification")
def generate_grab_gil(self, code):
if self.entry.type.with_gil:
code.putln("")
code.put_py_gil_state_ensure(Naming.gilstate_cname)
code.putln("")
def generate_release_gil(self, code):
if self.entry.type.with_gil:
code.putln("")
code.put_py_gil_state_release(Naming.gilstate_cname)
code.putln("")
def error_value(self):
if self.return_type.is_pyobject:
return "0"
......
......@@ -1455,10 +1455,10 @@ def p_c_declarator(s, empty = 0, is_type = 0, cmethod_flag = 0 , assignable = 0)
args = p_c_arg_list(s, in_pyfunc = 0, cmethod_flag = cmethod_flag)
ellipsis = p_optional_ellipsis(s)
s.expect(')')
exc_val, exc_check = p_exception_value_clause(s)
options = p_c_func_options(s)
result = Nodes.CFuncDeclaratorNode(pos,
base = result, args = args, has_varargs = ellipsis,
exception_value = exc_val, exception_check = exc_check)
**options)
cmethod_flag = 0
return result
......@@ -1477,6 +1477,32 @@ def p_exception_value_clause(s):
exc_val = p_simple_expr(s) #p_exception_value(s)
return exc_val, exc_check
def p_c_with_gil(s):
if s.sy == 'withGIL':
s.next()
return True
return False
def p_c_func_options(s):
exc_val = None
exc_check = 0
with_gil = False
if s.sy == 'except':
exc_val, exc_check = p_exception_value_clause(s)
with_gil = p_c_with_gil(s)
elif s.sy == 'withGIL':
with_gil = p_c_with_gil(s)
exc_val, exc_check = p_exception_value_clause(s)
ret = {
'exception_value': exc_val,
'exception_check': exc_check,
'with_gil': with_gil,
}
return ret
#def p_exception_value(s):
# sign = ""
# if s.sy == "-":
......
......@@ -493,16 +493,18 @@ class CFuncType(CType):
# has_varargs boolean
# exception_value string
# exception_check boolean True if PyErr_Occurred check needed
# with_gil boolean True if GIL should be grabbed/released
is_cfunction = 1
def __init__(self, return_type, args, has_varargs,
exception_value = None, exception_check = 0):
exception_value = None, exception_check = 0, with_gil = False):
self.return_type = return_type
self.args = args
self.has_varargs = has_varargs
self.exception_value = exception_value
self.exception_check = exception_check
self.with_gil = with_gil
def __repr__(self):
arg_reprs = map(repr, self.args)
......@@ -585,6 +587,7 @@ class CFuncType(CType):
if not arg_decl_code and not pyrex:
arg_decl_code = "void"
exc_clause = ""
with_gil_clause = ""
if pyrex or for_display:
if self.exception_value and self.exception_check:
exc_clause = " except? %s" % self.exception_value
......@@ -592,8 +595,11 @@ class CFuncType(CType):
exc_clause = " except %s" % self.exception_value
elif self.exception_check:
exc_clause = " except *"
if self.with_gil:
with_gil_clause = " withGIL"
return self.return_type.declaration_code(
"(%s(%s)%s)" % (entity_code, arg_decl_code, exc_clause),
"(%s(%s)%s%s)" % (entity_code, arg_decl_code,
exc_clause, with_gil_clause),
for_display, dll_linkage, pyrex)
......
......@@ -138,7 +138,7 @@ reserved_words = [
"raise", "import", "exec", "try", "except", "finally",
"while", "if", "elif", "else", "for", "in", "assert",
"and", "or", "not", "is", "in", "lambda", "from",
"NULL", "cimport", "by"
"NULL", "cimport", "by", "withGIL"
]
class Method:
......
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