diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2024-11-07 09:32:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-07 09:32:42 -0700 |
commit | 9357fdcaf0b08dac9396c17e8695b420fad887f8 (patch) | |
tree | f1c67448dae4cc2b116e7a3a01c9e464760dbaf1 /Python/crossinterp.c | |
parent | 3d9f9ae5a7c4739fe319aa436ab1834d6765b0ac (diff) | |
download | cpython-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.c | 131 |
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 |