99#include "pycore_code.h" // _PyCode_HAS_EXECUTORS()
1010#include "pycore_crossinterp.h" // _PyXIData_t
1111#include "pycore_interp.h" // _PyInterpreterState_IDIncref()
12+ #include "pycore_memoryobject.h" // _PyMemoryView_GetXIBuffewViewType()
1213#include "pycore_modsupport.h" // _PyArg_BadArgument()
1314#include "pycore_namespace.h" // _PyNamespace_New()
1415#include "pycore_pybuffer.h" // _PyBuffer_ReleaseInInterpreterAndRawFree()
@@ -36,23 +37,6 @@ _get_current_interp(void)
3637#define look_up_interp _PyInterpreterState_LookUpIDObject
3738
3839
39- static PyObject *
40- _get_current_module (void )
41- {
42- PyObject * name = PyUnicode_FromString (MODULE_NAME_STR );
43- if (name == NULL ) {
44- return NULL ;
45- }
46- PyObject * mod = PyImport_GetModule (name );
47- Py_DECREF (name );
48- if (mod == NULL ) {
49- return NULL ;
50- }
51- assert (mod != Py_None );
52- return mod ;
53- }
54-
55-
5640static int
5741is_running_main (PyInterpreterState * interp )
5842{
@@ -71,204 +55,10 @@ is_running_main(PyInterpreterState *interp)
7155}
7256
7357
74- /* Cross-interpreter Buffer Views *******************************************/
75-
76- // XXX Release when the original interpreter is destroyed.
77-
78- typedef struct {
79- PyObject base ;
80- Py_buffer * view ;
81- int64_t interpid ;
82- } XIBufferViewObject ;
83-
84- #define XIBufferViewObject_CAST (op ) ((XIBufferViewObject *)(op))
85-
86- static PyObject *
87- xibufferview_from_buffer (PyTypeObject * cls , Py_buffer * view , int64_t interpid )
88- {
89- assert (interpid >= 0 );
90-
91- Py_buffer * copied = PyMem_RawMalloc (sizeof (Py_buffer ));
92- if (copied == NULL ) {
93- return NULL ;
94- }
95- /* This steals the view->obj reference */
96- * copied = * view ;
97-
98- XIBufferViewObject * self = PyObject_Malloc (sizeof (XIBufferViewObject ));
99- if (self == NULL ) {
100- PyMem_RawFree (copied );
101- return NULL ;
102- }
103- PyObject_Init (& self -> base , cls );
104- * self = (XIBufferViewObject ){
105- .base = self -> base ,
106- .view = copied ,
107- .interpid = interpid ,
108- };
109- return (PyObject * )self ;
110- }
111-
112- static void
113- xibufferview_dealloc (PyObject * op )
114- {
115- XIBufferViewObject * self = XIBufferViewObject_CAST (op );
116-
117- if (self -> view != NULL ) {
118- PyInterpreterState * interp =
119- _PyInterpreterState_LookUpID (self -> interpid );
120- if (interp == NULL ) {
121- /* The interpreter is no longer alive. */
122- PyErr_Clear ();
123- PyMem_RawFree (self -> view );
124- }
125- else {
126- if (_PyBuffer_ReleaseInInterpreterAndRawFree (interp ,
127- self -> view ) < 0 )
128- {
129- // XXX Emit a warning?
130- PyErr_Clear ();
131- }
132- }
133- }
134-
135- PyTypeObject * tp = Py_TYPE (self );
136- tp -> tp_free (self );
137- /* "Instances of heap-allocated types hold a reference to their type."
138- * See: https://docs.python.org/3.11/howto/isolating-extensions.html#garbage-collection-protocol
139- * See: https://docs.python.org/3.11/c-api/typeobj.html#c.PyTypeObject.tp_traverse
140- */
141- // XXX Why don't we implement Py_TPFLAGS_HAVE_GC, e.g. Py_tp_traverse,
142- // like we do for _abc._abc_data?
143- Py_DECREF (tp );
144- }
145-
146- static int
147- xibufferview_getbuf (PyObject * op , Py_buffer * view , int flags )
148- {
149- /* Only PyMemoryView_FromObject() should ever call this,
150- via _memoryview_from_xid() below. */
151- XIBufferViewObject * self = XIBufferViewObject_CAST (op );
152- * view = * self -> view ;
153- view -> obj = op ;
154- // XXX Should we leave it alone?
155- view -> internal = NULL ;
156- return 0 ;
157- }
158-
159- static PyType_Slot XIBufferViewType_slots [] = {
160- {Py_tp_dealloc , xibufferview_dealloc },
161- {Py_bf_getbuffer , xibufferview_getbuf },
162- // We don't bother with Py_bf_releasebuffer since we don't need it.
163- {0 , NULL },
164- };
165-
166- static PyType_Spec XIBufferViewType_spec = {
167- .name = MODULE_NAME_STR ".CrossInterpreterBufferView" ,
168- .basicsize = sizeof (XIBufferViewObject ),
169- .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
170- Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE ),
171- .slots = XIBufferViewType_slots ,
172- };
173-
174-
175- static PyTypeObject * _get_current_xibufferview_type (void );
176-
177-
178- struct xibuffer {
179- Py_buffer view ;
180- int used ;
181- };
182-
183- static PyObject *
184- _memoryview_from_xid (_PyXIData_t * data )
185- {
186- assert (_PyXIData_DATA (data ) != NULL );
187- assert (_PyXIData_OBJ (data ) == NULL );
188- assert (_PyXIData_INTERPID (data ) >= 0 );
189- struct xibuffer * view = (struct xibuffer * )_PyXIData_DATA (data );
190- assert (!view -> used );
191-
192- PyTypeObject * cls = _get_current_xibufferview_type ();
193- if (cls == NULL ) {
194- return NULL ;
195- }
196-
197- PyObject * obj = xibufferview_from_buffer (
198- cls , & view -> view , _PyXIData_INTERPID (data ));
199- if (obj == NULL ) {
200- return NULL ;
201- }
202- PyObject * res = PyMemoryView_FromObject (obj );
203- if (res == NULL ) {
204- Py_DECREF (obj );
205- return NULL ;
206- }
207- view -> used = 1 ;
208- return res ;
209- }
210-
211- static void
212- _pybuffer_shared_free (void * data )
213- {
214- struct xibuffer * view = (struct xibuffer * )data ;
215- if (!view -> used ) {
216- PyBuffer_Release (& view -> view );
217- }
218- PyMem_RawFree (data );
219- }
220-
221- static int
222- _pybuffer_shared (PyThreadState * tstate , PyObject * obj , _PyXIData_t * data )
223- {
224- struct xibuffer * view = PyMem_RawMalloc (sizeof (struct xibuffer ));
225- if (view == NULL ) {
226- return -1 ;
227- }
228- view -> used = 0 ;
229- if (PyObject_GetBuffer (obj , & view -> view , PyBUF_FULL_RO ) < 0 ) {
230- PyMem_RawFree (view );
231- return -1 ;
232- }
233- _PyXIData_Init (data , tstate -> interp , view , NULL , _memoryview_from_xid );
234- data -> free = _pybuffer_shared_free ;
235- return 0 ;
236- }
237-
238- static int
239- register_memoryview_xid (PyObject * mod , PyTypeObject * * p_state )
240- {
241- // XIBufferView
242- assert (* p_state == NULL );
243- PyTypeObject * cls = (PyTypeObject * )PyType_FromModuleAndSpec (
244- mod , & XIBufferViewType_spec , NULL );
245- if (cls == NULL ) {
246- return -1 ;
247- }
248- if (PyModule_AddType (mod , cls ) < 0 ) {
249- Py_DECREF (cls );
250- return -1 ;
251- }
252- * p_state = cls ;
253-
254- // Register XID for the builtin memoryview type.
255- if (ensure_xid_class (& PyMemoryView_Type , _pybuffer_shared ) < 0 ) {
256- return -1 ;
257- }
258- // We don't ever bother un-registering memoryview.
259-
260- return 0 ;
261- }
262-
263-
264-
26558/* module state *************************************************************/
26659
26760typedef struct {
26861 int _notused ;
269-
270- /* heap types */
271- PyTypeObject * XIBufferViewType ;
27262} module_state ;
27363
27464static inline module_state *
@@ -280,51 +70,19 @@ get_module_state(PyObject *mod)
28070 return state ;
28171}
28272
283- static module_state *
284- _get_current_module_state (void )
285- {
286- PyObject * mod = _get_current_module ();
287- if (mod == NULL ) {
288- // XXX import it?
289- PyErr_SetString (PyExc_RuntimeError ,
290- MODULE_NAME_STR " module not imported yet" );
291- return NULL ;
292- }
293- module_state * state = get_module_state (mod );
294- Py_DECREF (mod );
295- return state ;
296- }
297-
29873static int
29974traverse_module_state (module_state * state , visitproc visit , void * arg )
30075{
301- /* heap types */
302- Py_VISIT (state -> XIBufferViewType );
303-
30476 return 0 ;
30577}
30678
30779static int
30880clear_module_state (module_state * state )
30981{
310- /* heap types */
311- Py_CLEAR (state -> XIBufferViewType );
312-
31382 return 0 ;
31483}
31584
31685
317- static PyTypeObject *
318- _get_current_xibufferview_type (void )
319- {
320- module_state * state = _get_current_module_state ();
321- if (state == NULL ) {
322- return NULL ;
323- }
324- return state -> XIBufferViewType ;
325- }
326-
327-
32886/* Python code **************************************************************/
32987
33088static const char *
@@ -1545,6 +1303,7 @@ module_exec(PyObject *mod)
15451303{
15461304 PyInterpreterState * interp = PyInterpreterState_Get ();
15471305 module_state * state = get_module_state (mod );
1306+ (void )state ;
15481307
15491308 _PyXIData_lookup_context_t ctx ;
15501309 if (_PyXIData_GetLookupContext (interp , & ctx ) < 0 ) {
@@ -1576,9 +1335,14 @@ module_exec(PyObject *mod)
15761335 goto error ;
15771336 }
15781337
1579- if (register_memoryview_xid (mod , & state -> XIBufferViewType ) < 0 ) {
1338+ PyTypeObject * XIBufferViewType = _PyMemoryView_GetXIBuffewViewType ();
1339+ if (XIBufferViewType == NULL ) {
15801340 goto error ;
15811341 }
1342+ if (PyModule_AddType (mod , XIBufferViewType ) < 0 ) {
1343+ Py_DECREF (XIBufferViewType );
1344+ return -1 ;
1345+ }
15821346
15831347 return 0 ;
15841348
0 commit comments