mirror of
https://github.com/python/cpython
synced 2024-10-14 10:33:27 +00:00
gh-112213: Add @critical_section target directive to Argument Clinic (gh-112232)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
607b5e30c6
commit
e52cc80f7f
|
@ -5542,3 +5542,173 @@ test_critical_section_meth_o(PyObject *module, PyObject *arg)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_critical_section_meth_o_impl(PyObject *module, PyObject *a)
|
test_critical_section_meth_o_impl(PyObject *module, PyObject *a)
|
||||||
/*[clinic end generated code: output=7a9d7420802d1202 input=376533f51eceb6c3]*/
|
/*[clinic end generated code: output=7a9d7420802d1202 input=376533f51eceb6c3]*/
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section a
|
||||||
|
test_critical_section_object
|
||||||
|
a: object(subclass_of="&PyUnicode_Type")
|
||||||
|
/
|
||||||
|
test_critical_section_object
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(test_critical_section_object__doc__,
|
||||||
|
"test_critical_section_object($module, a, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"test_critical_section_object");
|
||||||
|
|
||||||
|
#define TEST_CRITICAL_SECTION_OBJECT_METHODDEF \
|
||||||
|
{"test_critical_section_object", (PyCFunction)test_critical_section_object, METH_O, test_critical_section_object__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object_impl(PyObject *module, PyObject *a);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object(PyObject *module, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *a;
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(arg)) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object", "argument", "str", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
a = arg;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(a);
|
||||||
|
return_value = test_critical_section_object_impl(module, a);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object_impl(PyObject *module, PyObject *a)
|
||||||
|
/*[clinic end generated code: output=ec06df92232b0fb5 input=6f67f91b523c875f]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(test_critical_section_object__doc__,
|
||||||
|
"test_critical_section_object($module, a, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"test_critical_section_object");
|
||||||
|
|
||||||
|
#define TEST_CRITICAL_SECTION_OBJECT_METHODDEF \
|
||||||
|
{"test_critical_section_object", (PyCFunction)test_critical_section_object, METH_O, test_critical_section_object__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object_impl(PyObject *module, PyObject *a);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object(PyObject *module, PyObject *arg)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *a;
|
||||||
|
|
||||||
|
if (!PyUnicode_Check(arg)) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object", "argument", "str", arg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
a = arg;
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(a);
|
||||||
|
return_value = test_critical_section_object_impl(module, a);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@critical_section a b
|
||||||
|
test_critical_section_object2
|
||||||
|
a: object(subclass_of="&PyUnicode_Type")
|
||||||
|
b: object(subclass_of="&PyUnicode_Type")
|
||||||
|
/
|
||||||
|
test_critical_section_object2
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(test_critical_section_object2__doc__,
|
||||||
|
"test_critical_section_object2($module, a, b, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"test_critical_section_object2");
|
||||||
|
|
||||||
|
#define TEST_CRITICAL_SECTION_OBJECT2_METHODDEF \
|
||||||
|
{"test_critical_section_object2", _PyCFunction_CAST(test_critical_section_object2), METH_FASTCALL, test_critical_section_object2__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object2_impl(PyObject *module, PyObject *a,
|
||||||
|
PyObject *b);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object2(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *a;
|
||||||
|
PyObject *b;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("test_critical_section_object2", nargs, 2, 2)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyUnicode_Check(args[0])) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object2", "argument 1", "str", args[0]);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
a = args[0];
|
||||||
|
if (!PyUnicode_Check(args[1])) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object2", "argument 2", "str", args[1]);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
b = args[1];
|
||||||
|
Py_BEGIN_CRITICAL_SECTION2(a, b);
|
||||||
|
return_value = test_critical_section_object2_impl(module, a, b);
|
||||||
|
Py_END_CRITICAL_SECTION2();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object2_impl(PyObject *module, PyObject *a,
|
||||||
|
PyObject *b)
|
||||||
|
/*[clinic end generated code: output=d73a1657c18df17a input=638824e41419a466]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(test_critical_section_object2__doc__,
|
||||||
|
"test_critical_section_object2($module, a, b, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"test_critical_section_object2");
|
||||||
|
|
||||||
|
#define TEST_CRITICAL_SECTION_OBJECT2_METHODDEF \
|
||||||
|
{"test_critical_section_object2", _PyCFunction_CAST(test_critical_section_object2), METH_FASTCALL, test_critical_section_object2__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object2_impl(PyObject *module, PyObject *a,
|
||||||
|
PyObject *b);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_critical_section_object2(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *a;
|
||||||
|
PyObject *b;
|
||||||
|
|
||||||
|
if (!_PyArg_CheckPositional("test_critical_section_object2", nargs, 2, 2)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!PyUnicode_Check(args[0])) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object2", "argument 1", "str", args[0]);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
a = args[0];
|
||||||
|
if (!PyUnicode_Check(args[1])) {
|
||||||
|
_PyArg_BadArgument("test_critical_section_object2", "argument 2", "str", args[1]);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
b = args[1];
|
||||||
|
Py_BEGIN_CRITICAL_SECTION2(a, b);
|
||||||
|
return_value = test_critical_section_object2_impl(module, a, b);
|
||||||
|
Py_END_CRITICAL_SECTION2();
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
|
@ -1866,8 +1866,18 @@ def render_function(
|
||||||
assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
|
assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
|
||||||
|
|
||||||
if f.critical_section:
|
if f.critical_section:
|
||||||
data.lock.append('Py_BEGIN_CRITICAL_SECTION({self_name});')
|
match len(f.target_critical_section):
|
||||||
data.unlock.append('Py_END_CRITICAL_SECTION();')
|
case 0:
|
||||||
|
lock = 'Py_BEGIN_CRITICAL_SECTION({self_name});'
|
||||||
|
unlock = 'Py_END_CRITICAL_SECTION();'
|
||||||
|
case 1:
|
||||||
|
lock = 'Py_BEGIN_CRITICAL_SECTION({target_critical_section});'
|
||||||
|
unlock = 'Py_END_CRITICAL_SECTION();'
|
||||||
|
case _:
|
||||||
|
lock = 'Py_BEGIN_CRITICAL_SECTION2({target_critical_section});'
|
||||||
|
unlock = 'Py_END_CRITICAL_SECTION2();'
|
||||||
|
data.lock.append(lock)
|
||||||
|
data.unlock.append(unlock)
|
||||||
|
|
||||||
last_group = 0
|
last_group = 0
|
||||||
first_optional = len(selfless)
|
first_optional = len(selfless)
|
||||||
|
@ -1922,6 +1932,7 @@ def render_function(
|
||||||
template_dict['docstring'] = self.docstring_for_c_string(f)
|
template_dict['docstring'] = self.docstring_for_c_string(f)
|
||||||
|
|
||||||
template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
|
template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
|
||||||
|
template_dict['target_critical_section'] = ', '.join(f.target_critical_section)
|
||||||
for converter in converters:
|
for converter in converters:
|
||||||
converter.set_template_dict(template_dict)
|
converter.set_template_dict(template_dict)
|
||||||
|
|
||||||
|
@ -2970,6 +2981,7 @@ class Function:
|
||||||
# those accurately with inspect.Signature in 3.4.
|
# those accurately with inspect.Signature in 3.4.
|
||||||
docstring_only: bool = False
|
docstring_only: bool = False
|
||||||
critical_section: bool = False
|
critical_section: bool = False
|
||||||
|
target_critical_section: list[str] = dc.field(default_factory=list)
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
self.parent = self.cls or self.module
|
self.parent = self.cls or self.module
|
||||||
|
@ -5160,6 +5172,7 @@ def reset(self) -> None:
|
||||||
self.parameter_continuation = ''
|
self.parameter_continuation = ''
|
||||||
self.preserve_output = False
|
self.preserve_output = False
|
||||||
self.critical_section = False
|
self.critical_section = False
|
||||||
|
self.target_critical_section: list[str] = []
|
||||||
|
|
||||||
def directive_version(self, required: str) -> None:
|
def directive_version(self, required: str) -> None:
|
||||||
global version
|
global version
|
||||||
|
@ -5288,7 +5301,10 @@ def at_classmethod(self) -> None:
|
||||||
fail("Can't set @classmethod, function is not a normal callable")
|
fail("Can't set @classmethod, function is not a normal callable")
|
||||||
self.kind = CLASS_METHOD
|
self.kind = CLASS_METHOD
|
||||||
|
|
||||||
def at_critical_section(self) -> None:
|
def at_critical_section(self, *args: str) -> None:
|
||||||
|
if len(args) > 2:
|
||||||
|
fail("Up to 2 critical section variables are supported")
|
||||||
|
self.target_critical_section.extend(args)
|
||||||
self.critical_section = True
|
self.critical_section = True
|
||||||
|
|
||||||
def at_staticmethod(self) -> None:
|
def at_staticmethod(self) -> None:
|
||||||
|
@ -5514,7 +5530,8 @@ def state_modulename_name(self, line: str) -> None:
|
||||||
|
|
||||||
self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
|
self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
|
||||||
return_converter=return_converter, kind=self.kind, coexist=self.coexist,
|
return_converter=return_converter, kind=self.kind, coexist=self.coexist,
|
||||||
critical_section=self.critical_section)
|
critical_section=self.critical_section,
|
||||||
|
target_critical_section=self.target_critical_section)
|
||||||
self.block.signatures.append(self.function)
|
self.block.signatures.append(self.function)
|
||||||
|
|
||||||
# insert a self converter automatically
|
# insert a self converter automatically
|
||||||
|
|
Loading…
Reference in a new issue