@@ -76,41 +76,60 @@ is_running_main(PyInterpreterState *interp)
76
76
// XXX Release when the original interpreter is destroyed.
77
77
78
78
typedef struct {
79
- PyObject_HEAD
79
+ PyObject base ;
80
80
Py_buffer * view ;
81
81
int64_t interpid ;
82
82
} XIBufferViewObject ;
83
83
84
84
#define XIBufferViewObject_CAST (op ) ((XIBufferViewObject *)(op))
85
85
86
86
static PyObject *
87
- xibufferview_from_xid (PyTypeObject * cls , _PyXIData_t * data )
87
+ xibufferview_from_buffer (PyTypeObject * cls , Py_buffer * view , int64_t interpid )
88
88
{
89
- assert (_PyXIData_DATA (data ) != NULL );
90
- assert (_PyXIData_OBJ (data ) == NULL );
91
- assert (_PyXIData_INTERPID (data ) >= 0 );
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
+
92
98
XIBufferViewObject * self = PyObject_Malloc (sizeof (XIBufferViewObject ));
93
99
if (self == NULL ) {
100
+ PyMem_RawFree (copied );
94
101
return NULL ;
95
102
}
96
- PyObject_Init ((PyObject * )self , cls );
97
- self -> view = (Py_buffer * )_PyXIData_DATA (data );
98
- self -> interpid = _PyXIData_INTERPID (data );
103
+ PyObject_Init (& self -> base , cls );
104
+ * self = (XIBufferViewObject ){
105
+ .base = self -> base ,
106
+ .view = copied ,
107
+ .interpid = interpid ,
108
+ };
99
109
return (PyObject * )self ;
100
110
}
101
111
102
112
static void
103
113
xibufferview_dealloc (PyObject * op )
104
114
{
105
115
XIBufferViewObject * self = XIBufferViewObject_CAST (op );
106
- PyInterpreterState * interp = _PyInterpreterState_LookUpID (self -> interpid );
107
- /* If the interpreter is no longer alive then we have problems,
108
- since other objects may be using the buffer still. */
109
- assert (interp != NULL );
110
116
111
- if (_PyBuffer_ReleaseInInterpreterAndRawFree (interp , self -> view ) < 0 ) {
112
- // XXX Emit a warning?
113
- PyErr_Clear ();
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
+ }
114
133
}
115
134
116
135
PyTypeObject * tp = Py_TYPE (self );
@@ -155,32 +174,64 @@ static PyType_Spec XIBufferViewType_spec = {
155
174
156
175
static PyTypeObject * _get_current_xibufferview_type (void );
157
176
177
+
178
+ struct xibuffer {
179
+ Py_buffer view ;
180
+ int used ;
181
+ };
182
+
158
183
static PyObject *
159
184
_memoryview_from_xid (_PyXIData_t * data )
160
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
+
161
192
PyTypeObject * cls = _get_current_xibufferview_type ();
162
193
if (cls == NULL ) {
163
194
return NULL ;
164
195
}
165
- PyObject * obj = xibufferview_from_xid (cls , data );
196
+
197
+ PyObject * obj = xibufferview_from_buffer (
198
+ cls , & view -> view , _PyXIData_INTERPID (data ));
166
199
if (obj == NULL ) {
167
200
return NULL ;
168
201
}
169
- return PyMemoryView_FromObject (obj );
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 );
170
219
}
171
220
172
221
static int
173
- _memoryview_shared (PyThreadState * tstate , PyObject * obj , _PyXIData_t * data )
222
+ _pybuffer_shared (PyThreadState * tstate , PyObject * obj , _PyXIData_t * data )
174
223
{
175
- Py_buffer * view = PyMem_RawMalloc (sizeof (Py_buffer ));
224
+ struct xibuffer * view = PyMem_RawMalloc (sizeof (struct xibuffer ));
176
225
if (view == NULL ) {
177
226
return -1 ;
178
227
}
179
- if (PyObject_GetBuffer (obj , view , PyBUF_FULL_RO ) < 0 ) {
228
+ view -> used = 0 ;
229
+ if (PyObject_GetBuffer (obj , & view -> view , PyBUF_FULL_RO ) < 0 ) {
180
230
PyMem_RawFree (view );
181
231
return -1 ;
182
232
}
183
233
_PyXIData_Init (data , tstate -> interp , view , NULL , _memoryview_from_xid );
234
+ data -> free = _pybuffer_shared_free ;
184
235
return 0 ;
185
236
}
186
237
@@ -201,7 +252,7 @@ register_memoryview_xid(PyObject *mod, PyTypeObject **p_state)
201
252
* p_state = cls ;
202
253
203
254
// Register XID for the builtin memoryview type.
204
- if (ensure_xid_class (& PyMemoryView_Type , _memoryview_shared ) < 0 ) {
255
+ if (ensure_xid_class (& PyMemoryView_Type , _pybuffer_shared ) < 0 ) {
205
256
return -1 ;
206
257
}
207
258
// We don't ever bother un-registering memoryview.
0 commit comments