@@ -82,6 +82,74 @@ API.. The module does not create any objects that are shared globally.
82
82
PyMem_RawFree(VAR)
83
83
84
84
85
+ struct xid_class_registry {
86
+ size_t count ;
87
+ #define MAX_XID_CLASSES 5
88
+ struct {
89
+ PyTypeObject * cls ;
90
+ } added [MAX_XID_CLASSES ];
91
+ };
92
+
93
+ static int
94
+ register_xid_class (PyTypeObject * cls , crossinterpdatafunc shared ,
95
+ struct xid_class_registry * classes )
96
+ {
97
+ int res = _PyCrossInterpreterData_RegisterClass (cls , shared );
98
+ if (res == 0 ) {
99
+ assert (classes -> count < MAX_XID_CLASSES );
100
+ Py_INCREF (cls );
101
+ classes -> added [classes -> count ].cls = cls ;
102
+ classes -> count += 1 ;
103
+ }
104
+ return res ;
105
+ }
106
+
107
+ static void
108
+ clear_xid_class_registry (struct xid_class_registry * classes )
109
+ {
110
+ while (classes -> count > 0 ) {
111
+ classes -> count -= 1 ;
112
+ PyTypeObject * cls = classes -> added [classes -> count ].cls ;
113
+ _PyCrossInterpreterData_UnregisterClass (cls );
114
+ Py_DECREF (cls );
115
+ }
116
+ }
117
+
118
+ #define XID_IGNORE_EXC 1
119
+ #define XID_FREE 2
120
+
121
+ static int
122
+ _release_xid_data (_PyCrossInterpreterData * data , int flags )
123
+ {
124
+ int ignoreexc = flags & XID_IGNORE_EXC ;
125
+ PyObject * exc ;
126
+ if (ignoreexc ) {
127
+ exc = PyErr_GetRaisedException ();
128
+ }
129
+ int res ;
130
+ if (flags & XID_FREE ) {
131
+ res = _PyCrossInterpreterData_ReleaseAndRawFree (data );
132
+ }
133
+ else {
134
+ res = _PyCrossInterpreterData_Release (data );
135
+ }
136
+ if (res < 0 ) {
137
+ /* The owning interpreter is already destroyed. */
138
+ if (ignoreexc ) {
139
+ // XXX Emit a warning?
140
+ PyErr_Clear ();
141
+ }
142
+ }
143
+ if (flags & XID_FREE ) {
144
+ /* Either way, we free the data. */
145
+ }
146
+ if (ignoreexc ) {
147
+ PyErr_SetRaisedException (exc );
148
+ }
149
+ return res ;
150
+ }
151
+
152
+
85
153
static PyInterpreterState *
86
154
_get_current_interp (void )
87
155
{
@@ -146,7 +214,8 @@ add_new_exception(PyObject *mod, const char *name, PyObject *base)
146
214
add_new_exception(MOD, MODULE_NAME "." Py_STRINGIFY(NAME), BASE)
147
215
148
216
static PyTypeObject *
149
- add_new_type (PyObject * mod , PyType_Spec * spec , crossinterpdatafunc shared )
217
+ add_new_type (PyObject * mod , PyType_Spec * spec , crossinterpdatafunc shared ,
218
+ struct xid_class_registry * classes )
150
219
{
151
220
PyTypeObject * cls = (PyTypeObject * )PyType_FromMetaclass (
152
221
NULL , mod , spec , NULL );
@@ -158,48 +227,14 @@ add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared)
158
227
return NULL ;
159
228
}
160
229
if (shared != NULL ) {
161
- if (_PyCrossInterpreterData_RegisterClass (cls , shared )) {
230
+ if (register_xid_class (cls , shared , classes )) {
162
231
Py_DECREF (cls );
163
232
return NULL ;
164
233
}
165
234
}
166
235
return cls ;
167
236
}
168
237
169
- #define XID_IGNORE_EXC 1
170
- #define XID_FREE 2
171
-
172
- static int
173
- _release_xid_data (_PyCrossInterpreterData * data , int flags )
174
- {
175
- int ignoreexc = flags & XID_IGNORE_EXC ;
176
- PyObject * exc ;
177
- if (ignoreexc ) {
178
- exc = PyErr_GetRaisedException ();
179
- }
180
- int res ;
181
- if (flags & XID_FREE ) {
182
- res = _PyCrossInterpreterData_ReleaseAndRawFree (data );
183
- }
184
- else {
185
- res = _PyCrossInterpreterData_Release (data );
186
- }
187
- if (res < 0 ) {
188
- /* The owning interpreter is already destroyed. */
189
- if (ignoreexc ) {
190
- // XXX Emit a warning?
191
- PyErr_Clear ();
192
- }
193
- }
194
- if (flags & XID_FREE ) {
195
- /* Either way, we free the data. */
196
- }
197
- if (ignoreexc ) {
198
- PyErr_SetRaisedException (exc );
199
- }
200
- return res ;
201
- }
202
-
203
238
204
239
/* Cross-interpreter Buffer Views *******************************************/
205
240
@@ -315,15 +350,15 @@ _memoryview_shared(PyThreadState *tstate, PyObject *obj,
315
350
}
316
351
317
352
static int
318
- register_xid_types ( void )
353
+ register_builtin_xid_types ( struct xid_class_registry * classes )
319
354
{
320
355
PyTypeObject * cls ;
321
356
crossinterpdatafunc func ;
322
357
323
358
// builtin memoryview
324
359
cls = & PyMemoryView_Type ;
325
360
func = _memoryview_shared ;
326
- if (_PyCrossInterpreterData_RegisterClass (cls , func )) {
361
+ if (register_xid_class (cls , func , classes )) {
327
362
return -1 ;
328
363
}
329
364
@@ -334,6 +369,9 @@ register_xid_types(void)
334
369
/* module state *************************************************************/
335
370
336
371
typedef struct {
372
+ struct xid_class_registry xid_classes ;
373
+
374
+ /* Added at runtime by interpreters module. */
337
375
PyTypeObject * send_channel_type ;
338
376
PyTypeObject * recv_channel_type ;
339
377
@@ -2191,6 +2229,7 @@ set_channel_end_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
2191
2229
if (state == NULL ) {
2192
2230
return -1 ;
2193
2231
}
2232
+ struct xid_class_registry * xid_classes = & state -> xid_classes ;
2194
2233
2195
2234
if (state -> send_channel_type != NULL
2196
2235
|| state -> recv_channel_type != NULL )
@@ -2201,10 +2240,10 @@ set_channel_end_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
2201
2240
state -> send_channel_type = (PyTypeObject * )Py_NewRef (send );
2202
2241
state -> recv_channel_type = (PyTypeObject * )Py_NewRef (recv );
2203
2242
2204
- if (_PyCrossInterpreterData_RegisterClass (send , _channel_end_shared )) {
2243
+ if (register_xid_class (send , _channel_end_shared , xid_classes )) {
2205
2244
return -1 ;
2206
2245
}
2207
- if (_PyCrossInterpreterData_RegisterClass (recv , _channel_end_shared )) {
2246
+ if (register_xid_class (recv , _channel_end_shared , xid_classes )) {
2208
2247
return -1 ;
2209
2248
}
2210
2249
@@ -2722,6 +2761,7 @@ module_exec(PyObject *mod)
2722
2761
if (_globals_init () != 0 ) {
2723
2762
return -1 ;
2724
2763
}
2764
+ struct xid_class_registry * xid_classes = NULL ;
2725
2765
2726
2766
/* Add exception types */
2727
2767
if (exceptions_init (mod ) != 0 ) {
@@ -2733,20 +2773,22 @@ module_exec(PyObject *mod)
2733
2773
if (state == NULL ) {
2734
2774
goto error ;
2735
2775
}
2776
+ xid_classes = & state -> xid_classes ;
2736
2777
2737
2778
// ChannelID
2738
2779
state -> ChannelIDType = add_new_type (
2739
- mod , & ChannelIDType_spec , _channelid_shared );
2780
+ mod , & ChannelIDType_spec , _channelid_shared , xid_classes );
2740
2781
if (state -> ChannelIDType == NULL ) {
2741
2782
goto error ;
2742
2783
}
2743
2784
2744
- state -> XIBufferViewType = add_new_type (mod , & XIBufferViewType_spec , NULL );
2785
+ state -> XIBufferViewType = add_new_type (mod , & XIBufferViewType_spec , NULL ,
2786
+ xid_classes );
2745
2787
if (state -> XIBufferViewType == NULL ) {
2746
2788
goto error ;
2747
2789
}
2748
2790
2749
- if (register_xid_types ( ) < 0 ) {
2791
+ if (register_builtin_xid_types ( xid_classes ) < 0 ) {
2750
2792
goto error ;
2751
2793
}
2752
2794
@@ -2757,6 +2799,9 @@ module_exec(PyObject *mod)
2757
2799
return 0 ;
2758
2800
2759
2801
error :
2802
+ if (xid_classes != NULL ) {
2803
+ clear_xid_class_registry (xid_classes );
2804
+ }
2760
2805
_globals_fini ();
2761
2806
return -1 ;
2762
2807
}
@@ -2781,6 +2826,11 @@ module_clear(PyObject *mod)
2781
2826
{
2782
2827
module_state * state = get_module_state (mod );
2783
2828
assert (state != NULL );
2829
+
2830
+ // Before clearing anything, we unregister the various XID types. */
2831
+ clear_xid_class_registry (& state -> xid_classes );
2832
+
2833
+ // Now we clear the module state.
2784
2834
clear_module_state (state );
2785
2835
return 0 ;
2786
2836
}
0 commit comments