diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2019-03-15 22:35:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-15 22:35:46 (GMT) |
commit | c11183cdcff6af13c4339fdcce84ab63f7930ddc (patch) | |
tree | 947655550e220dc5ddfd5079fa2a92ebdac9dbef /Include | |
parent | 842a2f07f2f08a935ef470bfdaeef40f87490cfc (diff) | |
download | cpython-c11183cdcff6af13c4339fdcce84ab63f7930ddc.zip cpython-c11183cdcff6af13c4339fdcce84ab63f7930ddc.tar.gz cpython-c11183cdcff6af13c4339fdcce84ab63f7930ddc.tar.bz2 |
bpo-36097: Use only public C-API in the_xxsubinterpreters module (adding as necessary). (gh-12359)
Diffstat (limited to 'Include')
-rw-r--r-- | Include/cpython/interpreteridobject.h | 21 | ||||
-rw-r--r-- | Include/cpython/pystate.h | 63 | ||||
-rw-r--r-- | Include/internal/pycore_pystate.h | 55 | ||||
-rw-r--r-- | Include/interpreteridobject.h | 17 |
4 files changed, 102 insertions, 54 deletions
diff --git a/Include/cpython/interpreteridobject.h b/Include/cpython/interpreteridobject.h new file mode 100644 index 0000000..cb72c2b --- /dev/null +++ b/Include/cpython/interpreteridobject.h @@ -0,0 +1,21 @@ +#ifndef Py_CPYTHON_INTERPRETERIDOBJECT_H +# error "this header file must not be included directly" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Interpreter ID Object */ + +PyAPI_DATA(PyTypeObject) _PyInterpreterID_Type; + +PyAPI_FUNC(PyObject *) _PyInterpreterID_New(int64_t); +PyAPI_FUNC(PyObject *) _PyInterpreterState_GetIDObject(PyInterpreterState *); +PyAPI_FUNC(PyInterpreterState *) _PyInterpreterID_LookUp(PyObject *); + +PyAPI_FUNC(int64_t) _Py_CoerceID(PyObject *); + +#ifdef __cplusplus +} +#endif diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 3fca78f..5439d07 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -30,9 +30,13 @@ typedef struct { (_PyMainInterpreterConfig){.install_signal_handlers = -1} /* Note: _PyMainInterpreterConfig_INIT sets other fields to 0/NULL */ +PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); + PyAPI_FUNC(_PyCoreConfig *) _PyInterpreterState_GetCoreConfig(PyInterpreterState *); PyAPI_FUNC(_PyMainInterpreterConfig *) _PyInterpreterState_GetMainConfig(PyInterpreterState *); +PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *); /* State unique per thread */ @@ -214,6 +218,65 @@ PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *); typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_); +/* cross-interpreter data */ + +struct _xid; + +// _PyCrossInterpreterData 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. +typedef struct _xid { + // data is the cross-interpreter-safe derivation of a Python object + // (see _PyObject_GetCrossInterpreterData). 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 + // 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 + // be set by the cross-interpreter machinery. + // + // We use the ID rather than the PyInterpreterState to avoid issues + // with deleted interpreters. Note that IDs are never re-used, so + // each one will always correspond to a specific interpreter + // (whether still alive or not). + int64_t interp; + // new_object is a function that returns a new object in the current + // interpreter given the data. The resulting object (a new + // reference) will be equivalent to the original object. This field + // is required. + PyObject *(*new_object)(struct _xid *); + // free is called when the data is released. If it is NULL then + // nothing will be done to free the data. For some types this is + // 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 + // 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. + void (*free)(void *); +} _PyCrossInterpreterData; + +PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); +PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); +PyAPI_FUNC(void) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); + +PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); + +/* cross-interpreter data registry */ + +typedef int (*crossinterpdatafunc)(PyObject *, struct _xid *); + +PyAPI_FUNC(int) _PyCrossInterpreterData_RegisterClass(PyTypeObject *, crossinterpdatafunc); +PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 456dda2..945d992 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -29,6 +29,7 @@ struct _is { int64_t id; int64_t id_refcount; + int requires_idref; PyThread_type_lock id_mutex; int finalizing; @@ -89,66 +90,12 @@ PyAPI_FUNC(void) _PyInterpreterState_IDIncref(struct _is *); PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *); -/* cross-interpreter data */ - -struct _xid; - -// _PyCrossInterpreterData 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. -typedef struct _xid { - // data is the cross-interpreter-safe derivation of a Python object - // (see _PyObject_GetCrossInterpreterData). 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 - // 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 - // be set by the cross-interpreter machinery. - // - // We use the ID rather than the PyInterpreterState to avoid issues - // with deleted interpreters. - int64_t interp; - // new_object is a function that returns a new object in the current - // interpreter given the data. The resulting object (a new - // reference) will be equivalent to the original object. This field - // is required. - PyObject *(*new_object)(struct _xid *); - // free is called when the data is released. If it is NULL then - // nothing will be done to free the data. For some types this is - // 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 - // 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. - void (*free)(void *); -} _PyCrossInterpreterData; - -typedef int (*crossinterpdatafunc)(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); - -PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); -PyAPI_FUNC(void) _PyCrossInterpreterData_Release(_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. */ -PyAPI_FUNC(int) _PyCrossInterpreterData_Register_Class(PyTypeObject *, crossinterpdatafunc); -PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); - struct _xidregitem; struct _xidregitem { diff --git a/Include/interpreteridobject.h b/Include/interpreteridobject.h new file mode 100644 index 0000000..e744fcd --- /dev/null +++ b/Include/interpreteridobject.h @@ -0,0 +1,17 @@ +#ifndef Py_INTERPRETERIDOBJECT_H +#define Py_INTERPRETERIDOBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +# define Py_CPYTHON_INTERPRETERIDOBJECT_H +# include "cpython/interpreteridobject.h" +# undef Py_CPYTHON_INTERPRETERIDOBJECT_H +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERPRETERIDOBJECT_H */ |