aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/crossinterp.c
diff options
context:
space:
mode:
authorAnthony Shaw <anthony.p.shaw@gmail.com>2023-11-08 02:58:29 +0900
committerGitHub <noreply@github.com>2023-11-07 10:58:29 -0700
commit178861b19324c94d98478e4c2bba075964c3baa4 (patch)
tree08bfa66e1f1a4348a18181ef857f9d5a4263cea8 /Python/crossinterp.c
parent70afb8d7324bc74fe64141e1af5c602bf6c0c4dd (diff)
downloadcpython-178861b19324c94d98478e4c2bba075964c3baa4.tar.gz
cpython-178861b19324c94d98478e4c2bba075964c3baa4.zip
gh-111623: Add Support for Cross-interpreter tuples (gh-111628)
Diffstat (limited to 'Python/crossinterp.c')
-rw-r--r--Python/crossinterp.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index de28cb70717..a908f9ae340 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 */