@@ -355,6 +355,9 @@ def __init__(self):
355355 # The C statements required to clean up after the impl call.
356356 self .cleanup = []
357357
358+ self .lock_statement = []
359+ self .unlock_statement = []
360+
358361
359362class FormatCounterFormatter (string .Formatter ):
360363 """
@@ -822,7 +825,9 @@ def parser_body(prototype, *fields, declarations=''):
822825 # just imagine--your code is here in the middle
823826 fields .append (normalize_snippet ("""
824827 {modifications}
828+ {lock_statement}
825829 {return_value} = {c_basename}_impl({impl_arguments});
830+ {unlock_statement}
826831 {return_conversion}
827832 {post_parsing}
828833
@@ -862,7 +867,7 @@ def parser_body(prototype, *fields, declarations=''):
862867 }}
863868 """ % return_error , indent = 4 )]
864869
865- if default_return_converter :
870+ if default_return_converter and not f . lock :
866871 parser_definition = '\n ' .join ([
867872 parser_prototype ,
868873 '{{' ,
@@ -882,7 +887,7 @@ def parser_body(prototype, *fields, declarations=''):
882887 {c_basename}({impl_parameters})
883888 """ )
884889
885- if default_return_converter :
890+ if default_return_converter and not f . lock :
886891 # maps perfectly to METH_O, doesn't need a return converter.
887892 # so we skip making a parse function
888893 # and call directly into the impl function.
@@ -1373,6 +1378,14 @@ def render_function(self, clinic, f):
13731378 selfless = parameters [1 :]
13741379 assert isinstance (f_self .converter , self_converter ), "No self parameter in " + repr (f .full_name ) + "!"
13751380
1381+ if f .lock is not None :
1382+ if f .lock == 'rlock' :
1383+ data .lock_statement .append ('_PyRecursiveMutex_lock(&{self_name}->{lock_name});' )
1384+ data .unlock_statement .append ('_PyRecursiveMutex_unlock(&{self_name}->{lock_name});' )
1385+ else :
1386+ data .lock_statement .append ('Py_BEGIN_CRITICAL_SECTION(&{self_name}->{lock_name});' )
1387+ data .unlock_statement .append ('Py_END_CRITICAL_SECTION;' )
1388+
13761389 last_group = 0
13771390 first_optional = len (selfless )
13781391 positional = selfless and selfless [- 1 ].is_positional_only ()
@@ -1474,6 +1487,10 @@ def render_function(self, clinic, f):
14741487 template_dict ['cleanup' ] = format_escape ("" .join (data .cleanup ))
14751488 template_dict ['return_value' ] = data .return_value
14761489
1490+ template_dict ['lock_name' ] = f .lock
1491+ template_dict ['lock_statement' ] = "\n " .join (data .lock_statement )
1492+ template_dict ['unlock_statement' ] = "\n " .join (data .unlock_statement )
1493+
14771494 # used by unpack tuple code generator
14781495 ignore_self = - 1 if isinstance (converters [0 ], self_converter ) else 0
14791496 unpack_min = first_optional
@@ -1497,6 +1514,8 @@ def render_function(self, clinic, f):
14971514 modifications = template_dict ['modifications' ],
14981515 post_parsing = template_dict ['post_parsing' ],
14991516 cleanup = template_dict ['cleanup' ],
1517+ lock_statement = template_dict ['lock_statement' ],
1518+ unlock_statement = template_dict ['unlock_statement' ],
15001519 )
15011520
15021521 # Only generate the "exit:" label
@@ -2371,7 +2390,7 @@ def __init__(self, parameters=None, *, name,
23712390 module , cls = None , c_basename = None ,
23722391 full_name = None ,
23732392 return_converter , return_annotation = inspect .Signature .empty ,
2374- docstring = None , kind = CALLABLE , coexist = False ,
2393+ docstring = None , kind = CALLABLE , coexist = False , lock = None ,
23752394 docstring_only = False ):
23762395 self .parameters = parameters or collections .OrderedDict ()
23772396 self .return_annotation = return_annotation
@@ -2385,6 +2404,7 @@ def __init__(self, parameters=None, *, name,
23852404 self .docstring = docstring or ''
23862405 self .kind = kind
23872406 self .coexist = coexist
2407+ self .lock = lock
23882408 self .self_converter = None
23892409 # docstring_only means "don't generate a machine-readable
23902410 # signature, just a normal docstring". it's True for
@@ -4362,10 +4382,12 @@ def state_modulename_name(self, line):
43624382 return
43634383
43644384 line , _ , returns = line .partition ('->' )
4385+ line , _ , lock = line .partition (' @ ' )
43654386
43664387 full_name , _ , c_basename = line .partition (' as ' )
43674388 full_name = full_name .strip ()
43684389 c_basename = c_basename .strip () or None
4390+ lock = lock .strip () or None
43694391
43704392 if not is_legal_py_identifier (full_name ):
43714393 fail ("Illegal function name: {}" .format (full_name ))
@@ -4418,7 +4440,7 @@ def state_modulename_name(self, line):
44184440 if not module :
44194441 fail ("Undefined module used in declaration of " + repr (full_name .strip ()) + "." )
44204442 self .function = Function (name = function_name , full_name = full_name , module = module , cls = cls , c_basename = c_basename ,
4421- return_converter = return_converter , kind = self .kind , coexist = self .coexist )
4443+ return_converter = return_converter , kind = self .kind , coexist = self .coexist , lock = lock )
44224444 self .block .signatures .append (self .function )
44234445
44244446 # insert a self converter automatically
0 commit comments