summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony Shaw <anthony.p.shaw@gmail.com>2023-11-07 17:58:29 (GMT)
committerGitHub <noreply@github.com>2023-11-07 17:58:29 (GMT)
commit178861b19324c94d98478e4c2bba075964c3baa4 (patch)
tree08bfa66e1f1a4348a18181ef857f9d5a4263cea8
parent70afb8d7324bc74fe64141e1af5c602bf6c0c4dd (diff)
downloadcpython-178861b19324c94d98478e4c2bba075964c3baa4.zip
cpython-178861b19324c94d98478e4c2bba075964c3baa4.tar.gz
cpython-178861b19324c94d98478e4c2bba075964c3baa4.tar.bz2
gh-111623: Add Support for Cross-interpreter tuples (gh-111628)
-rw-r--r--Lib/test/test__xxsubinterpreters.py28
-rw-r--r--Lib/test/test_interpreters.py2
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-10-29-11-35-21.gh-issue-111435.ageUWQ.rst3
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-10-29-12-33-33.gh-issue-111438.bHTLLl.rst3
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-11-02-15-00-57.gh-issue-111623.BZxYc8.rst2
-rw-r--r--Python/crossinterp.c98
6 files changed, 134 insertions, 2 deletions
diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py
index ae7dfa1..97314dd 100644
--- a/Lib/test/test__xxsubinterpreters.py
+++ b/Lib/test/test__xxsubinterpreters.py
@@ -105,6 +105,7 @@ class IsShareableTests(unittest.TestCase):
True,
False,
100.0,
+ (1, ('spam', 'eggs')),
]
for obj in shareables:
with self.subTest(obj):
@@ -195,6 +196,33 @@ class ShareableTypeTests(unittest.TestCase):
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):
diff --git a/Lib/test/test_interpreters.py b/Lib/test/test_interpreters.py
index 74f8608..7c030bc 100644
--- a/Lib/test/test_interpreters.py
+++ b/Lib/test/test_interpreters.py
@@ -781,6 +781,8 @@ class TestIsShareable(TestBase):
True,
False,
100.0,
+ (),
+ (1, ('spam', 'eggs'), True),
]
for obj in shareables:
with self.subTest(obj):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-29-11-35-21.gh-issue-111435.ageUWQ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-29-11-35-21.gh-issue-111435.ageUWQ.rst
index 95044dc..0346155 100644
--- a/Misc/NEWS.d/next/Core and Builtins/2023-10-29-11-35-21.gh-issue-111435.ageUWQ.rst
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-29-11-35-21.gh-issue-111435.ageUWQ.rst
@@ -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.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-29-12-33-33.gh-issue-111438.bHTLLl.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-29-12-33-33.gh-issue-111438.bHTLLl.rst
index b181977..009ba11 100644
--- a/Misc/NEWS.d/next/Core and Builtins/2023-10-29-12-33-33.gh-issue-111438.bHTLLl.rst
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-29-12-33-33.gh-issue-111438.bHTLLl.rst
@@ -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.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-02-15-00-57.gh-issue-111623.BZxYc8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-02-15-00-57.gh-issue-111623.BZxYc8.rst
new file mode 100644
index 0000000..3a75d5e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-11-02-15-00-57.gh-issue-111623.BZxYc8.rst
@@ -0,0 +1,2 @@
+Add support for sharing tuples between interpreters using the cross-interpreter
+API. Patch by Anthony Shaw.
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index de28cb7..a908f9a 100644
--- a/Python/crossinterp.c
+++ b/Python/crossinterp.c
@@ -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 */