aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/crossinterp.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2024-11-07 09:32:42 -0700
committerGitHub <noreply@github.com>2024-11-07 09:32:42 -0700
commit9357fdcaf0b08dac9396c17e8695b420fad887f8 (patch)
treef1c67448dae4cc2b116e7a3a01c9e464760dbaf1 /Python/crossinterp.c
parent3d9f9ae5a7c4739fe319aa436ab1834d6765b0ac (diff)
downloadcpython-9357fdcaf0b08dac9396c17e8695b420fad887f8.tar.gz
cpython-9357fdcaf0b08dac9396c17e8695b420fad887f8.zip
gh-76785: Minor Cleanup of "Cross-interpreter" Code (gh-126457)
The primary objective here is to allow some later changes to be cleaner. Mostly this involves renaming things and moving a few things around. * CrossInterpreterData -> XIData * crossinterpdatafunc -> xidatafunc * split out pycore_crossinterp_data_registry.h * add _PyXIData_lookup_t
Diffstat (limited to 'Python/crossinterp.c')
-rw-r--r--Python/crossinterp.c131
1 files changed, 69 insertions, 62 deletions
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index 0aca322d987..2daba99988c 100644
--- a/Python/crossinterp.c
+++ b/Python/crossinterp.c
@@ -3,11 +3,14 @@
#include "Python.h"
#include "pycore_ceval.h" // _Py_simple_func
-#include "pycore_crossinterp.h" // struct _xid
+#include "pycore_crossinterp.h" // _PyXIData_t
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_namespace.h" //_PyNamespace_New()
#include "pycore_pyerrors.h" // _PyErr_Clear()
-#include "pycore_weakref.h" // _PyWeakref_GET_REF()
+
+
+#define _PyXI_GET_GLOBAL_STATE(interp) (&(interp)->runtime->xi)
+#define _PyXI_GET_STATE(interp) (&(interp)->xi)
/**************/
@@ -57,25 +60,24 @@ _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
/* cross-interpreter data */
/**************************/
-/* registry of {type -> crossinterpdatafunc} */
+/* registry of {type -> xidatafunc} */
/* For now we use a global registry of shareable classes. An
alternative would be to add a tp_* slot for a class's
- crossinterpdatafunc. It would be simpler and more efficient. */
+ xidatafunc. It would be simpler and more efficient. */
-static void xid_lookup_init(PyInterpreterState *);
-static void xid_lookup_fini(PyInterpreterState *);
-static crossinterpdatafunc lookup_getdata(PyInterpreterState *, PyObject *);
+static void xid_lookup_init(_PyXIData_lookup_t *);
+static void xid_lookup_fini(_PyXIData_lookup_t *);
+static xidatafunc lookup_getdata(PyInterpreterState *, PyObject *);
#include "crossinterp_data_lookup.h"
/* lifecycle */
-_PyCrossInterpreterData *
-_PyCrossInterpreterData_New(void)
+_PyXIData_t *
+_PyXIData_New(void)
{
- _PyCrossInterpreterData *xid = PyMem_RawMalloc(
- sizeof(_PyCrossInterpreterData));
+ _PyXIData_t *xid = PyMem_RawMalloc(sizeof(_PyXIData_t));
if (xid == NULL) {
PyErr_NoMemory();
}
@@ -83,10 +85,10 @@ _PyCrossInterpreterData_New(void)
}
void
-_PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid)
+_PyXIData_Free(_PyXIData_t *xid)
{
PyInterpreterState *interp = PyInterpreterState_Get();
- _PyCrossInterpreterData_Clear(interp, xid);
+ _PyXIData_Clear(interp, xid);
PyMem_RawFree(xid);
}
@@ -94,20 +96,20 @@ _PyCrossInterpreterData_Free(_PyCrossInterpreterData *xid)
/* defining cross-interpreter data */
static inline void
-_xidata_init(_PyCrossInterpreterData *data)
+_xidata_init(_PyXIData_t *data)
{
// If the value is being reused
// then _xidata_clear() should have been called already.
assert(data->data == NULL);
assert(data->obj == NULL);
- *data = (_PyCrossInterpreterData){0};
- _PyCrossInterpreterData_INTERPID(data) = -1;
+ *data = (_PyXIData_t){0};
+ _PyXIData_INTERPID(data) = -1;
}
static inline void
-_xidata_clear(_PyCrossInterpreterData *data)
+_xidata_clear(_PyXIData_t *data)
{
- // _PyCrossInterpreterData only has two members that need to be
+ // _PyXIData_t only has two members that need to be
// cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
// In both cases the original (owning) interpreter must be used,
// which is the caller's responsibility to ensure.
@@ -121,10 +123,10 @@ _xidata_clear(_PyCrossInterpreterData *data)
}
void
-_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data,
- PyInterpreterState *interp,
- void *shared, PyObject *obj,
- xid_newobjectfunc new_object)
+_PyXIData_Init(_PyXIData_t *data,
+ PyInterpreterState *interp,
+ void *shared, PyObject *obj,
+ xid_newobjectfunc new_object)
{
assert(data != NULL);
assert(new_object != NULL);
@@ -132,29 +134,29 @@ _PyCrossInterpreterData_Init(_PyCrossInterpreterData *data,
data->data = shared;
if (obj != NULL) {
assert(interp != NULL);
- // released in _PyCrossInterpreterData_Clear()
+ // released in _PyXIData_Clear()
data->obj = Py_NewRef(obj);
}
// Ideally every object would know its owning interpreter.
// Until then, we have to rely on the caller to identify it
// (but we don't need it in all cases).
- _PyCrossInterpreterData_INTERPID(data) = (interp != NULL)
+ _PyXIData_INTERPID(data) = (interp != NULL)
? PyInterpreterState_GetID(interp)
: -1;
data->new_object = new_object;
}
int
-_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,
- PyInterpreterState *interp,
- const size_t size, PyObject *obj,
- xid_newobjectfunc new_object)
+_PyXIData_InitWithSize(_PyXIData_t *data,
+ PyInterpreterState *interp,
+ const size_t size, PyObject *obj,
+ xid_newobjectfunc new_object)
{
assert(size > 0);
// For now we always free the shared data in the same interpreter
// where it was allocated, so the interpreter is required.
assert(interp != NULL);
- _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object);
+ _PyXIData_Init(data, interp, NULL, obj, new_object);
data->data = PyMem_RawMalloc(size);
if (data->data == NULL) {
return -1;
@@ -164,14 +166,13 @@ _PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,
}
void
-_PyCrossInterpreterData_Clear(PyInterpreterState *interp,
- _PyCrossInterpreterData *data)
+_PyXIData_Clear(PyInterpreterState *interp, _PyXIData_t *data)
{
assert(data != NULL);
// This must be called in the owning interpreter.
assert(interp == NULL
- || _PyCrossInterpreterData_INTERPID(data) == -1
- || _PyCrossInterpreterData_INTERPID(data) == PyInterpreterState_GetID(interp));
+ || _PyXIData_INTERPID(data) == -1
+ || _PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp));
_xidata_clear(data);
}
@@ -179,13 +180,13 @@ _PyCrossInterpreterData_Clear(PyInterpreterState *interp,
/* using cross-interpreter data */
static int
-_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data)
+_check_xidata(PyThreadState *tstate, _PyXIData_t *data)
{
// data->data can be anything, including NULL, so we don't check it.
// data->obj may be NULL, so we don't check it.
- if (_PyCrossInterpreterData_INTERPID(data) < 0) {
+ if (_PyXIData_INTERPID(data) < 0) {
PyErr_SetString(PyExc_SystemError, "missing interp");
return -1;
}
@@ -221,10 +222,10 @@ _set_xid_lookup_failure(PyInterpreterState *interp,
}
int
-_PyObject_CheckCrossInterpreterData(PyObject *obj)
+_PyObject_CheckXIData(PyObject *obj)
{
PyInterpreterState *interp = PyInterpreterState_Get();
- crossinterpdatafunc getdata = lookup_getdata(interp, obj);
+ xidatafunc getdata = lookup_getdata(interp, obj);
if (getdata == NULL) {
if (!PyErr_Occurred()) {
_set_xid_lookup_failure(interp, obj, NULL);
@@ -235,18 +236,18 @@ _PyObject_CheckCrossInterpreterData(PyObject *obj)
}
int
-_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
+_PyObject_GetXIData(PyObject *obj, _PyXIData_t *data)
{
PyThreadState *tstate = PyThreadState_Get();
PyInterpreterState *interp = tstate->interp;
// Reset data before re-populating.
- *data = (_PyCrossInterpreterData){0};
- _PyCrossInterpreterData_INTERPID(data) = -1;
+ *data = (_PyXIData_t){0};
+ _PyXIData_INTERPID(data) = -1;
// Call the "getdata" func for the object.
Py_INCREF(obj);
- crossinterpdatafunc getdata = lookup_getdata(interp, obj);
+ xidatafunc getdata = lookup_getdata(interp, obj);
if (getdata == NULL) {
Py_DECREF(obj);
if (!PyErr_Occurred()) {
@@ -261,9 +262,9 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
}
// Fill in the blanks and validate the result.
- _PyCrossInterpreterData_INTERPID(data) = PyInterpreterState_GetID(interp);
+ _PyXIData_INTERPID(data) = PyInterpreterState_GetID(interp);
if (_check_xidata(tstate, data) != 0) {
- (void)_PyCrossInterpreterData_Release(data);
+ (void)_PyXIData_Release(data);
return -1;
}
@@ -271,7 +272,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
}
PyObject *
-_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
+_PyXIData_NewObject(_PyXIData_t *data)
{
return data->new_object(data);
}
@@ -279,12 +280,12 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
static int
_call_clear_xidata(void *data)
{
- _xidata_clear((_PyCrossInterpreterData *)data);
+ _xidata_clear((_PyXIData_t *)data);
return 0;
}
static int
-_xidata_release(_PyCrossInterpreterData *data, int rawfree)
+_xidata_release(_PyXIData_t *data, int rawfree)
{
if ((data->data == NULL || data->free == NULL) && data->obj == NULL) {
// Nothing to release!
@@ -299,7 +300,7 @@ _xidata_release(_PyCrossInterpreterData *data, int rawfree)
// Switch to the original interpreter.
PyInterpreterState *interp = _PyInterpreterState_LookUpID(
- _PyCrossInterpreterData_INTERPID(data));
+ _PyXIData_INTERPID(data));
if (interp == NULL) {
// The interpreter was already destroyed.
// This function shouldn't have been called.
@@ -321,13 +322,13 @@ _xidata_release(_PyCrossInterpreterData *data, int rawfree)
}
int
-_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
+_PyXIData_Release(_PyXIData_t *data)
{
return _xidata_release(data, 0);
}
int
-_PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *data)
+_PyXIData_ReleaseAndRawFree(_PyXIData_t *data)
{
return _xidata_release(data, 1);
}
@@ -446,15 +447,15 @@ _format_TracebackException(PyObject *tbexc)
static int
-_release_xid_data(_PyCrossInterpreterData *data, int rawfree)
+_release_xid_data(_PyXIData_t *data, int rawfree)
{
PyObject *exc = PyErr_GetRaisedException();
int res = rawfree
- ? _PyCrossInterpreterData_Release(data)
- : _PyCrossInterpreterData_ReleaseAndRawFree(data);
+ ? _PyXIData_Release(data)
+ : _PyXIData_ReleaseAndRawFree(data);
if (res < 0) {
/* The owning interpreter is already destroyed. */
- _PyCrossInterpreterData_Clear(NULL, data);
+ _PyXIData_Clear(NULL, data);
// XXX Emit a warning?
PyErr_Clear();
}
@@ -1094,8 +1095,8 @@ _PyXI_ApplyError(_PyXI_error *error)
typedef struct _sharednsitem {
const char *name;
- _PyCrossInterpreterData *data;
- // We could have a "PyCrossInterpreterData _data" field, so it would
+ _PyXIData_t *data;
+ // We could have a "PyXIData _data" field, so it would
// be allocated as part of the item and avoid an extra allocation.
// However, doing so adds a bunch of complexity because we must
// ensure the item isn't freed before a pending call might happen
@@ -1131,7 +1132,7 @@ _sharednsitem_has_value(_PyXI_namespace_item *item, int64_t *p_interpid)
return 0;
}
if (p_interpid != NULL) {
- *p_interpid = _PyCrossInterpreterData_INTERPID(item->data);
+ *p_interpid = _PyXIData_INTERPID(item->data);
}
return 1;
}
@@ -1141,12 +1142,12 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value)
{
assert(_sharednsitem_is_initialized(item));
assert(item->data == NULL);
- item->data = PyMem_RawMalloc(sizeof(_PyCrossInterpreterData));
+ item->data = PyMem_RawMalloc(sizeof(_PyXIData_t));
if (item->data == NULL) {
PyErr_NoMemory();
return -1;
}
- if (_PyObject_GetCrossInterpreterData(value, item->data) != 0) {
+ if (_PyObject_GetXIData(value, item->data) != 0) {
PyMem_RawFree(item->data);
item->data = NULL;
// The caller may want to propagate PyExc_NotShareableError
@@ -1159,7 +1160,7 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value)
static void
_sharednsitem_clear_value(_PyXI_namespace_item *item)
{
- _PyCrossInterpreterData *data = item->data;
+ _PyXIData_t *data = item->data;
if (data != NULL) {
item->data = NULL;
int rawfree = 1;
@@ -1205,7 +1206,7 @@ _sharednsitem_apply(_PyXI_namespace_item *item, PyObject *ns, PyObject *dflt)
}
PyObject *value;
if (item->data != NULL) {
- value = _PyCrossInterpreterData_NewObject(item->data);
+ value = _PyXIData_NewObject(item->data);
if (value == NULL) {
Py_DECREF(name);
return -1;
@@ -1776,7 +1777,10 @@ PyStatus
_PyXI_Init(PyInterpreterState *interp)
{
// Initialize the XID lookup state (e.g. registry).
- xid_lookup_init(interp);
+ if (_Py_IsMainInterpreter(interp)) {
+ xid_lookup_init(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup);
+ }
+ xid_lookup_init(&_PyXI_GET_STATE(interp)->data_lookup);
// Initialize exceptions (heap types).
if (_init_not_shareable_error_type(interp) < 0) {
@@ -1796,7 +1800,10 @@ _PyXI_Fini(PyInterpreterState *interp)
_fini_not_shareable_error_type(interp);
// Finalize the XID lookup state (e.g. registry).
- xid_lookup_fini(interp);
+ xid_lookup_fini(&_PyXI_GET_STATE(interp)->data_lookup);
+ if (_Py_IsMainInterpreter(interp)) {
+ xid_lookup_fini(&_PyXI_GET_GLOBAL_STATE(interp)->data_lookup);
+ }
}
PyStatus