# 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
else: # neither src nor dst are py types
# Added the string comparison, since for c types that
# is enough, but SageX gets confused when the types are
- # in different files.
+ # in different files.
if not (str(src.type) == str(dst_type) or dst_type.assignable_from(src_type)):
error(self.pos, "Cannot assign type '%s' to '%s'" %
(src.type, dst_type))
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"
# 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 = []
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)
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)
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:
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.
else:
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"
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
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 == "-":
# 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)
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
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)
"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: