Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
CrossInterpreterData -> XIData
  • Loading branch information
ericsnowcurrently committed Nov 5, 2024
commit 9057584614339bbc3cc662da6745532c0391a225
47 changes: 23 additions & 24 deletions Include/internal/pycore_crossinterp.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ typedef void (*xid_freefunc)(void *);
// is necessary to pass safely between interpreters in the same process.
struct _xid {
// data is the cross-interpreter-safe derivation of a Python object
// (see _PyObject_GetCrossInterpreterData). It will be NULL if the
// (see _PyObject_GetXIData). It will be NULL if the
// new_object func (below) encodes the data.
void *data;
// obj is the Python object from which the data was derived. This
Expand All @@ -59,7 +59,7 @@ struct _xid {
PyObject *obj;
// interp is the ID of the owning interpreter of the original
// object. It corresponds to the active interpreter when
// _PyObject_GetCrossInterpreterData() was called. This should only
// _PyObject_GetXIData() was called. This should only
// be set by the cross-interpreter machinery.
//
// We use the ID rather than the PyInterpreterState to avoid issues
Expand All @@ -77,62 +77,61 @@ struct _xid {
// okay (e.g. bytes) and for those types this field should be set
// to NULL. However, for most the data was allocated just for
// cross-interpreter use, so it must be freed when
// _PyCrossInterpreterData_Release is called or the memory will
// _PyXIData_Release is called or the memory will
// leak. In that case, at the very least this field should be set
// to PyMem_RawFree (the default if not explicitly set to NULL).
// The call will happen with the original interpreter activated.
xid_freefunc free;
};

PyAPI_FUNC(_PyXIData_t *) _PyCrossInterpreterData_New(void);
PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyXIData_t *data);
PyAPI_FUNC(_PyXIData_t *) _PyXIData_New(void);
PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);

#define _PyCrossInterpreterData_DATA(DATA) ((DATA)->data)
#define _PyCrossInterpreterData_OBJ(DATA) ((DATA)->obj)
#define _PyCrossInterpreterData_INTERPID(DATA) ((DATA)->interpid)
#define _PyXIData_DATA(DATA) ((DATA)->data)
#define _PyXIData_OBJ(DATA) ((DATA)->obj)
#define _PyXIData_INTERPID(DATA) ((DATA)->interpid)
// Users should not need getters for "new_object" or "free".


/* defining cross-interpreter data */

PyAPI_FUNC(void) _PyCrossInterpreterData_Init(
PyAPI_FUNC(void) _PyXIData_Init(
_PyXIData_t *data,
PyInterpreterState *interp, void *shared, PyObject *obj,
xid_newobjectfunc new_object);
PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize(
PyAPI_FUNC(int) _PyXIData_InitWithSize(
_PyXIData_t *,
PyInterpreterState *interp, const size_t, PyObject *,
xid_newobjectfunc);
PyAPI_FUNC(void) _PyCrossInterpreterData_Clear(
PyInterpreterState *, _PyXIData_t *);
PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);

// Normally the Init* functions are sufficient. The only time
// additional initialization might be needed is to set the "free" func,
// though that should be infrequent.
#define _PyCrossInterpreterData_SET_FREE(DATA, FUNC) \
#define _PyXIData_SET_FREE(DATA, FUNC) \
do { \
(DATA)->free = (FUNC); \
} while (0)
// Additionally, some shareable types are essentially light wrappers
// around other shareable types. The xidatafunc of the wrapper
// can often be implemented by calling the wrapped object's
// xidatafunc and then changing the "new_object" function.
// We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that,
// We have _PyXIData_SET_NEW_OBJECT() here for that,
// but might be better to have a function like
// _PyCrossInterpreterData_AdaptToWrapper() instead.
#define _PyCrossInterpreterData_SET_NEW_OBJECT(DATA, FUNC) \
// _PyXIData_AdaptToWrapper() instead.
#define _PyXIData_SET_NEW_OBJECT(DATA, FUNC) \
do { \
(DATA)->new_object = (FUNC); \
} while (0)


/* using cross-interpreter data */

PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *);
PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyXIData_t *);
PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyXIData_t *);
PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyXIData_t *);
PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyXIData_t *);
PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *);
PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *);
PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *);
PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *);
PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *);


/* cross-interpreter data registry */
Expand Down Expand Up @@ -163,9 +162,9 @@ struct _xidregistry {
struct _xidregitem *head;
};

PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, xidatafunc);
PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *);
PyAPI_FUNC(xidatafunc) _PyCrossInterpreterData_Lookup(PyObject *);
PyAPI_FUNC(int) _PyXIData_RegisterClass(PyTypeObject *, xidatafunc);
PyAPI_FUNC(int) _PyXIData_UnregisterClass(PyTypeObject *);
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *);


/*****************************/
Expand Down
26 changes: 12 additions & 14 deletions Modules/_interpchannelsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The above state includes the following allocations by the module:
* 1 _PyXIData_t

The only objects in that global state are the references held by each
channel's queue, which are safely managed via the _PyCrossInterpreterData_*()
channel's queue, which are safely managed via the _PyXIData_*()
API.. The module does not create any objects that are shared globally.
*/

Expand Down Expand Up @@ -111,10 +111,10 @@ _release_xid_data(_PyXIData_t *data, int flags)
}
int res;
if (flags & XID_FREE) {
res = _PyCrossInterpreterData_ReleaseAndRawFree(data);
res = _PyXIData_ReleaseAndRawFree(data);
}
else {
res = _PyCrossInterpreterData_Release(data);
res = _PyXIData_Release(data);
}
if (res < 0) {
/* The owning interpreter is already destroyed. */
Expand Down Expand Up @@ -541,8 +541,8 @@ _channelitem_init(_channelitem *item,
}
else {
assert(data == NULL
|| _PyCrossInterpreterData_INTERPID(data) < 0
|| interpid == _PyCrossInterpreterData_INTERPID(data));
|| _PyXIData_INTERPID(data) < 0
|| interpid == _PyXIData_INTERPID(data));
}
*item = (_channelitem){
.interpid = interpid,
Expand Down Expand Up @@ -634,7 +634,7 @@ _channelitem_clear_interpreter(_channelitem *item)
assert(item->unboundop != UNBOUND_REMOVE);
return 0;
}
assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid);
assert(_PyXIData_INTERPID(item->data) == item->interpid);

switch (item->unboundop) {
case UNBOUND_REMOVE:
Expand Down Expand Up @@ -1779,7 +1779,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
PyThread_release_lock(mutex);
return -1;
}
if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
if (_PyObject_GetXIData(obj, data) != 0) {
PyThread_release_lock(mutex);
GLOBAL_FREE(data);
return -1;
Expand Down Expand Up @@ -1917,7 +1917,7 @@ channel_recv(_channels *channels, int64_t cid, PyObject **res, int *p_unboundop)
}

// Convert the data back to an object.
PyObject *obj = _PyCrossInterpreterData_NewObject(data);
PyObject *obj = _PyXIData_NewObject(data);
if (obj == NULL) {
assert(PyErr_Occurred());
// It was allocated in channel_send(), so we free it.
Expand Down Expand Up @@ -2545,8 +2545,7 @@ struct _channelid_xid {
static PyObject *
_channelid_from_xid(_PyXIData_t *data)
{
struct _channelid_xid *xid = \
(struct _channelid_xid *)_PyCrossInterpreterData_DATA(data);
struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data);

// It might not be imported yet, so we can't use _get_current_module().
PyObject *mod = PyImport_ImportModule(MODULE_NAME_STR);
Expand Down Expand Up @@ -2594,15 +2593,14 @@ _channelid_from_xid(_PyXIData_t *data)
static int
_channelid_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
{
if (_PyCrossInterpreterData_InitWithSize(
if (_PyXIData_InitWithSize(
data, tstate->interp, sizeof(struct _channelid_xid), obj,
_channelid_from_xid
) < 0)
{
return -1;
}
struct _channelid_xid *xid = \
(struct _channelid_xid *)_PyCrossInterpreterData_DATA(data);
struct _channelid_xid *xid = (struct _channelid_xid *)_PyXIData_DATA(data);
xid->cid = ((channelid *)obj)->cid;
xid->end = ((channelid *)obj)->end;
xid->resolve = ((channelid *)obj)->resolve;
Expand Down Expand Up @@ -2770,7 +2768,7 @@ _channelend_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
if (res < 0) {
return -1;
}
_PyCrossInterpreterData_SET_NEW_OBJECT(data, _channelend_from_xid);
_PyXIData_SET_NEW_OBJECT(data, _channelend_from_xid);
return 0;
}

Expand Down
23 changes: 11 additions & 12 deletions Modules/_interpqueuesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ _release_xid_data(_PyXIData_t *data, int flags)
}
int res;
if (flags & XID_FREE) {
res = _PyCrossInterpreterData_ReleaseAndRawFree(data);
res = _PyXIData_ReleaseAndRawFree(data);
}
else {
res = _PyCrossInterpreterData_Release(data);
res = _PyXIData_Release(data);
}
if (res < 0) {
/* The owning interpreter is already destroyed. */
Expand Down Expand Up @@ -415,8 +415,8 @@ _queueitem_init(_queueitem *item,
}
else {
assert(data == NULL
|| _PyCrossInterpreterData_INTERPID(data) < 0
|| interpid == _PyCrossInterpreterData_INTERPID(data));
|| _PyXIData_INTERPID(data) < 0
|| interpid == _PyXIData_INTERPID(data));
}
assert(check_unbound(unboundop));
*item = (_queueitem){
Expand Down Expand Up @@ -496,7 +496,7 @@ _queueitem_clear_interpreter(_queueitem *item)
assert(item->unboundop != UNBOUND_REMOVE);
return 0;
}
assert(_PyCrossInterpreterData_INTERPID(item->data) == item->interpid);
assert(_PyXIData_INTERPID(item->data) == item->interpid);

switch (item->unboundop) {
case UNBOUND_REMOVE:
Expand Down Expand Up @@ -1141,12 +1141,12 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
_queue_unmark_waiter(queue, queues->mutex);
return -1;
}
if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
if (_PyObject_GetXIData(obj, data) != 0) {
_queue_unmark_waiter(queue, queues->mutex);
GLOBAL_FREE(data);
return -1;
}
assert(_PyCrossInterpreterData_INTERPID(data) == \
assert(_PyXIData_INTERPID(data) == \
PyInterpreterState_GetID(PyInterpreterState_Get()));

// Add the data to the queue.
Expand Down Expand Up @@ -1194,7 +1194,7 @@ queue_get(_queues *queues, int64_t qid,
}

// Convert the data back to an object.
PyObject *obj = _PyCrossInterpreterData_NewObject(data);
PyObject *obj = _PyXIData_NewObject(data);
if (obj == NULL) {
assert(PyErr_Occurred());
// It was allocated in queue_put(), so we free it.
Expand Down Expand Up @@ -1338,7 +1338,7 @@ _queueid_xid_free(void *data)
static PyObject *
_queueobj_from_xid(_PyXIData_t *data)
{
int64_t qid = *(int64_t *)_PyCrossInterpreterData_DATA(data);
int64_t qid = *(int64_t *)_PyXIData_DATA(data);
PyObject *qidobj = PyLong_FromLongLong(qid);
if (qidobj == NULL) {
return NULL;
Expand Down Expand Up @@ -1384,9 +1384,8 @@ _queueobj_shared(PyThreadState *tstate, PyObject *queueobj, _PyXIData_t *data)
if (raw == NULL) {
return -1;
}
_PyCrossInterpreterData_Init(data, tstate->interp, raw, NULL,
_queueobj_from_xid);
_PyCrossInterpreterData_SET_FREE(data, _queueid_xid_free);
_PyXIData_Init(data, tstate->interp, raw, NULL, _queueobj_from_xid);
_PyXIData_SET_FREE(data, _queueid_xid_free);
return 0;
}

Expand Down
6 changes: 3 additions & 3 deletions Modules/_interpreters_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ static int
ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
{
//assert(cls->tp_flags & Py_TPFLAGS_HEAPTYPE);
return _PyCrossInterpreterData_RegisterClass(cls, getdata);
return _PyXIData_RegisterClass(cls, getdata);
}

#ifdef REGISTERS_HEAP_TYPES
static int
clear_xid_class(PyTypeObject *cls)
{
return _PyCrossInterpreterData_UnregisterClass(cls);
return _PyXIData_UnregisterClass(cls);
}
#endif

Expand All @@ -26,7 +26,7 @@ _get_interpid(_PyXIData_t *data)
{
int64_t interpid;
if (data != NULL) {
interpid = _PyCrossInterpreterData_INTERPID(data);
interpid = _PyXIData_INTERPID(data);
assert(!PyErr_Occurred());
}
else {
Expand Down
15 changes: 7 additions & 8 deletions Modules/_interpretersmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,16 @@ typedef struct {
static PyObject *
xibufferview_from_xid(PyTypeObject *cls, _PyXIData_t *data)
{
assert(_PyCrossInterpreterData_DATA(data) != NULL);
assert(_PyCrossInterpreterData_OBJ(data) == NULL);
assert(_PyCrossInterpreterData_INTERPID(data) >= 0);
assert(_PyXIData_DATA(data) != NULL);
assert(_PyXIData_OBJ(data) == NULL);
assert(_PyXIData_INTERPID(data) >= 0);
XIBufferViewObject *self = PyObject_Malloc(sizeof(XIBufferViewObject));
if (self == NULL) {
return NULL;
}
PyObject_Init((PyObject *)self, cls);
self->view = (Py_buffer *)_PyCrossInterpreterData_DATA(data);
self->interpid = _PyCrossInterpreterData_INTERPID(data);
self->view = (Py_buffer *)_PyXIData_DATA(data);
self->interpid = _PyXIData_INTERPID(data);
return (PyObject *)self;
}

Expand Down Expand Up @@ -178,8 +178,7 @@ _memoryview_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
PyMem_RawFree(view);
return -1;
}
_PyCrossInterpreterData_Init(data, tstate->interp, view, NULL,
_memoryview_from_xid);
_PyXIData_Init(data, tstate->interp, view, NULL, _memoryview_from_xid);
return 0;
}

Expand Down Expand Up @@ -1182,7 +1181,7 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}

if (_PyObject_CheckCrossInterpreterData(obj) == 0) {
if (_PyObject_CheckXIData(obj) == 0) {
Py_RETURN_TRUE;
}
PyErr_Clear();
Expand Down
16 changes: 8 additions & 8 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1788,8 +1788,8 @@ _xid_capsule_destructor(PyObject *capsule)
{
_PyXIData_t *data = (_PyXIData_t *)PyCapsule_GetPointer(capsule, NULL);
if (data != NULL) {
assert(_PyCrossInterpreterData_Release(data) == 0);
_PyCrossInterpreterData_Free(data);
assert(_PyXIData_Release(data) == 0);
_PyXIData_Free(data);
}
}

Expand All @@ -1801,18 +1801,18 @@ get_crossinterp_data(PyObject *self, PyObject *args)
return NULL;
}

_PyXIData_t *data = _PyCrossInterpreterData_New();
_PyXIData_t *data = _PyXIData_New();
if (data == NULL) {
return NULL;
}
if (_PyObject_GetCrossInterpreterData(obj, data) != 0) {
_PyCrossInterpreterData_Free(data);
if (_PyObject_GetXIData(obj, data) != 0) {
_PyXIData_Free(data);
return NULL;
}
PyObject *capsule = PyCapsule_New(data, NULL, _xid_capsule_destructor);
if (capsule == NULL) {
assert(_PyCrossInterpreterData_Release(data) == 0);
_PyCrossInterpreterData_Free(data);
assert(_PyXIData_Release(data) == 0);
_PyXIData_Free(data);
}
return capsule;
}
Expand All @@ -1829,7 +1829,7 @@ restore_crossinterp_data(PyObject *self, PyObject *args)
if (data == NULL) {
return NULL;
}
return _PyCrossInterpreterData_NewObject(data);
return _PyXIData_NewObject(data);
}


Expand Down
Loading