diff options
Diffstat (limited to 'Include/internal/pycore_crossinterp.h')
-rw-r--r-- | Include/internal/pycore_crossinterp.h | 114 |
1 files changed, 46 insertions, 68 deletions
diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h index 2dd165e..e91e911 100644 --- a/Include/internal/pycore_crossinterp.h +++ b/Include/internal/pycore_crossinterp.h @@ -38,28 +38,28 @@ extern int _Py_CallInInterpreterAndRawFree( /* cross-interpreter data */ /**************************/ -typedef struct _xid _PyCrossInterpreterData; -typedef PyObject *(*xid_newobjectfunc)(_PyCrossInterpreterData *); +typedef struct _xid _PyXIData_t; +typedef PyObject *(*xid_newobjectfunc)(_PyXIData_t *); typedef void (*xid_freefunc)(void *); -// _PyCrossInterpreterData is similar to Py_buffer as an effectively +// _PyXIData_t is similar to Py_buffer as an effectively // opaque struct that holds data outside the object machinery. This // 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 // is non-NULL only if the data remains bound to the object in some // way, such that the object must be "released" (via a decref) when // the data is released. In that case the code that sets the field, - // likely a registered "crossinterpdatafunc", is responsible for + // likely a registered "xidatafunc", is responsible for // ensuring it owns the reference (i.e. incref). 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 @@ -77,96 +77,77 @@ 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(_PyCrossInterpreterData *) _PyCrossInterpreterData_New(void); -PyAPI_FUNC(void) _PyCrossInterpreterData_Free(_PyCrossInterpreterData *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". +/* getting cross-interpreter data */ + +typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *); + +typedef struct _xid_lookup_state _PyXIData_lookup_t; + +PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(PyObject *); +PyAPI_FUNC(int) _PyObject_CheckXIData(PyObject *); +PyAPI_FUNC(int) _PyObject_GetXIData(PyObject *, _PyXIData_t *); + + +/* using cross-interpreter data */ + +PyAPI_FUNC(PyObject *) _PyXIData_NewObject(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_Release(_PyXIData_t *); +PyAPI_FUNC(int) _PyXIData_ReleaseAndRawFree(_PyXIData_t *); + + /* defining cross-interpreter data */ -PyAPI_FUNC(void) _PyCrossInterpreterData_Init( - _PyCrossInterpreterData *data, +PyAPI_FUNC(void) _PyXIData_Init( + _PyXIData_t *data, PyInterpreterState *interp, void *shared, PyObject *obj, xid_newobjectfunc new_object); -PyAPI_FUNC(int) _PyCrossInterpreterData_InitWithSize( - _PyCrossInterpreterData *, +PyAPI_FUNC(int) _PyXIData_InitWithSize( + _PyXIData_t *, PyInterpreterState *interp, const size_t, PyObject *, xid_newobjectfunc); -PyAPI_FUNC(void) _PyCrossInterpreterData_Clear( - PyInterpreterState *, _PyCrossInterpreterData *); +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 crossinterpdatafunc of the wrapper +// around other shareable types. The xidatafunc of the wrapper // can often be implemented by calling the wrapped object's -// crossinterpdatafunc and then changing the "new_object" function. -// We have _PyCrossInterpreterData_SET_NEW_OBJECT() here for that, +// xidatafunc and then changing the "new_object" function. +// 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 *, _PyCrossInterpreterData *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyCrossInterpreterData_ReleaseAndRawFree(_PyCrossInterpreterData *); - - /* cross-interpreter data registry */ -// 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. - -typedef int (*crossinterpdatafunc)(PyThreadState *tstate, PyObject *, - _PyCrossInterpreterData *); - -struct _xidregitem; - -struct _xidregitem { - struct _xidregitem *prev; - struct _xidregitem *next; - /* This can be a dangling pointer, but only if weakref is set. */ - PyTypeObject *cls; - /* This is NULL for builtin types. */ - PyObject *weakref; - size_t refcount; - crossinterpdatafunc getdata; -}; - -struct _xidregistry { - int global; /* builtin types or heap types */ - int initialized; - PyMutex mutex; - struct _xidregitem *head; -}; - -PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); -PyAPI_FUNC(int) _PyCrossInterpreterData_UnregisterClass(PyTypeObject *); -PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); +#define Py_CORE_CROSSINTERP_DATA_REGISTRY_H +#include "pycore_crossinterp_data_registry.h" +#undef Py_CORE_CROSSINTERP_DATA_REGISTRY_H /*****************************/ @@ -175,14 +156,12 @@ PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); struct _xi_runtime_state { // builtin types - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry registry; + _PyXIData_lookup_t data_lookup; }; struct _xi_state { // heap types - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry registry; + _PyXIData_lookup_t data_lookup; // heap types PyObject *PyExc_NotShareableError; @@ -190,7 +169,6 @@ struct _xi_state { extern PyStatus _PyXI_Init(PyInterpreterState *interp); extern void _PyXI_Fini(PyInterpreterState *interp); - extern PyStatus _PyXI_InitTypes(PyInterpreterState *interp); extern void _PyXI_FiniTypes(PyInterpreterState *interp); |