mirror of
https://github.com/python/cpython
synced 2024-10-14 11:58:12 +00:00
gh-111623: Add Support for Cross-interpreter tuples (gh-111628)
This commit is contained in:
parent
70afb8d732
commit
178861b193
|
@ -105,6 +105,7 @@ def test_default_shareables(self):
|
|||
True,
|
||||
False,
|
||||
100.0,
|
||||
(1, ('spam', 'eggs')),
|
||||
]
|
||||
for obj in shareables:
|
||||
with self.subTest(obj):
|
||||
|
@ -195,6 +196,33 @@ def test_bool(self):
|
|||
def test_float(self):
|
||||
self._assert_values([0.0, 1.1, -1.0, 0.12345678, -0.12345678])
|
||||
|
||||
def test_tuple(self):
|
||||
self._assert_values([(), (1,), ("hello", "world", ), (1, True, "hello")])
|
||||
# Test nesting
|
||||
self._assert_values([
|
||||
((1,),),
|
||||
((1, 2), (3, 4)),
|
||||
((1, 2), (3, 4), (5, 6)),
|
||||
])
|
||||
|
||||
def test_tuples_containing_non_shareable_types(self):
|
||||
non_shareables = [
|
||||
Exception(),
|
||||
object(),
|
||||
]
|
||||
for s in non_shareables:
|
||||
value = tuple([0, 1.0, s])
|
||||
with self.subTest(repr(value)):
|
||||
# XXX Assert the NotShareableError when it is exported
|
||||
with self.assertRaises(ValueError):
|
||||
_testinternalcapi.get_crossinterp_data(value)
|
||||
# Check nested as well
|
||||
value = tuple([0, 1., (s,)])
|
||||
with self.subTest("nested " + repr(value)):
|
||||
# XXX Assert the NotShareableError when it is exported
|
||||
with self.assertRaises(ValueError):
|
||||
_testinternalcapi.get_crossinterp_data(value)
|
||||
|
||||
|
||||
class ModuleTests(TestBase):
|
||||
|
||||
|
|
|
@ -781,6 +781,8 @@ def test_default_shareables(self):
|
|||
True,
|
||||
False,
|
||||
100.0,
|
||||
(),
|
||||
(1, ('spam', 'eggs'), True),
|
||||
]
|
||||
for obj in shareables:
|
||||
with self.subTest(obj):
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
Added support for sharing of bool type with interpreters API.
|
||||
Add support for sharing of True and False between interpreters using the cross-interpreter
|
||||
API. Patch by Anthony Shaw.
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
Added support for sharing of float type with interpreters API.
|
||||
Add support for sharing floats between interpreters using the cross-interpreter
|
||||
API. Patch by Anthony Shaw.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Add support for sharing tuples between interpreters using the cross-interpreter
|
||||
API. Patch by Anthony Shaw.
|
|
@ -713,6 +713,99 @@ _bool_shared(PyThreadState *tstate, PyObject *obj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct _shared_tuple_data {
|
||||
Py_ssize_t len;
|
||||
_PyCrossInterpreterData **data;
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
_new_tuple_object(_PyCrossInterpreterData *data)
|
||||
{
|
||||
struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data->data);
|
||||
PyObject *tuple = PyTuple_New(shared->len);
|
||||
if (tuple == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (Py_ssize_t i = 0; i < shared->len; i++) {
|
||||
PyObject *item = _PyCrossInterpreterData_NewObject(shared->data[i]);
|
||||
if (item == NULL){
|
||||
Py_DECREF(tuple);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(tuple, i, item);
|
||||
}
|
||||
return tuple;
|
||||
}
|
||||
|
||||
static void
|
||||
_tuple_shared_free(void* data)
|
||||
{
|
||||
struct _shared_tuple_data *shared = (struct _shared_tuple_data *)(data);
|
||||
#ifndef NDEBUG
|
||||
int64_t interpid = PyInterpreterState_GetID(_PyInterpreterState_GET());
|
||||
#endif
|
||||
for (Py_ssize_t i = 0; i < shared->len; i++) {
|
||||
if (shared->data[i] != NULL) {
|
||||
assert(shared->data[i]->interpid == interpid);
|
||||
_PyCrossInterpreterData_Release(shared->data[i]);
|
||||
PyMem_RawFree(shared->data[i]);
|
||||
shared->data[i] = NULL;
|
||||
}
|
||||
}
|
||||
PyMem_Free(shared->data);
|
||||
PyMem_RawFree(shared);
|
||||
}
|
||||
|
||||
static int
|
||||
_tuple_shared(PyThreadState *tstate, PyObject *obj,
|
||||
_PyCrossInterpreterData *data)
|
||||
{
|
||||
Py_ssize_t len = PyTuple_GET_SIZE(obj);
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
}
|
||||
struct _shared_tuple_data *shared = PyMem_RawMalloc(sizeof(struct _shared_tuple_data));
|
||||
if (shared == NULL){
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
shared->len = len;
|
||||
shared->data = (_PyCrossInterpreterData **) PyMem_Calloc(shared->len, sizeof(_PyCrossInterpreterData *));
|
||||
if (shared->data == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (Py_ssize_t i = 0; i < shared->len; i++) {
|
||||
_PyCrossInterpreterData *data = _PyCrossInterpreterData_New();
|
||||
if (data == NULL) {
|
||||
goto error; // PyErr_NoMemory already set
|
||||
}
|
||||
PyObject *item = PyTuple_GET_ITEM(obj, i);
|
||||
|
||||
int res = -1;
|
||||
if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) {
|
||||
res = _PyObject_GetCrossInterpreterData(item, data);
|
||||
_Py_LeaveRecursiveCallTstate(tstate);
|
||||
}
|
||||
if (res < 0) {
|
||||
PyMem_RawFree(data);
|
||||
goto error;
|
||||
}
|
||||
shared->data[i] = data;
|
||||
}
|
||||
_PyCrossInterpreterData_Init(
|
||||
data, tstate->interp, shared, obj, _new_tuple_object);
|
||||
data->free = _tuple_shared_free;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
_tuple_shared_free(shared);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
|
||||
{
|
||||
|
@ -745,6 +838,11 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
|
|||
if (_xidregistry_add_type(xidregistry, &PyFloat_Type, _float_shared) != 0) {
|
||||
Py_FatalError("could not register float for cross-interpreter sharing");
|
||||
}
|
||||
|
||||
// tuple
|
||||
if (_xidregistry_add_type(xidregistry, &PyTuple_Type, _tuple_shared) != 0) {
|
||||
Py_FatalError("could not register tuple for cross-interpreter sharing");
|
||||
}
|
||||
}
|
||||
|
||||
/* registry lifecycle */
|
||||
|
|
Loading…
Reference in a new issue