@@ -219,70 +219,86 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
219
219
* ==========================
220
220
*/
221
221
222
- /* To make a new object participate in garbage collection use
223
- PyObject_{New, VarNew, Del} to manage the memory. Set the type flag
224
- Py_TPFLAGS_GC and define the type method tp_traverse. You should also
225
- add the method tp_clear if your object is mutable. Include
226
- PyGC_HEAD_SIZE in the calculation of tp_basicsize. Call
227
- PyObject_GC_Init after the pointers followed by tp_traverse become
228
- valid (usually just before returning the object from the allocation
229
- method. Call PyObject_GC_Fini before those pointers become invalid
230
- (usually at the top of the deallocation method). */
231
-
232
- #ifndef WITH_CYCLE_GC
222
+ /* Test if a type has a GC head */
223
+ #define PyType_IS_GC (t ) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
233
224
234
- #define PyGC_HEAD_SIZE 0
235
- #define PyObject_GC_Init (op )
236
- #define PyObject_GC_Fini (op )
237
- #define PyObject_AS_GC (op ) (op)
238
- #define PyObject_FROM_GC (op ) (op)
239
- #define PyType_IS_GC (t ) 0
240
- #define PyObject_IS_GC (o ) 0
241
- #define PyType_BASICSIZE (t ) ((t)->tp_basicsize)
242
- #define PyType_SET_BASICSIZE (t , s ) ((t)->tp_basicsize = (s))
225
+ /* Test if an object has a GC head */
226
+ #define PyObject_IS_GC (o ) PyType_IS_GC((o)->ob_type)
243
227
244
- #else
228
+ extern DL_IMPORT (PyObject * ) _PyObject_GC_Malloc (PyTypeObject * , int );
229
+ extern DL_IMPORT (PyVarObject * ) _PyObject_GC_Resize (PyVarObject * , int );
245
230
246
- /* Add the object into the container set */
247
- extern DL_IMPORT ( void ) _PyGC_Insert ( PyObject * );
231
+ #define PyObject_GC_Resize ( type , op , n ) \
232
+ ( (type *) _PyObject_GC_Resize((PyVarObject *)(op), (n)) )
248
233
249
- /* Remove the object from the container set */
250
- extern DL_IMPORT (void ) _PyGC_Remove (PyObject * );
234
+ #ifdef WITH_CYCLE_GC
251
235
252
- #define PyObject_GC_Init (op ) _PyGC_Insert((PyObject *)op)
253
- #define PyObject_GC_Fini (op ) _PyGC_Remove((PyObject *)op)
236
+ extern DL_IMPORT (PyObject * ) _PyObject_GC_New (PyTypeObject * );
237
+ extern DL_IMPORT (PyVarObject * ) _PyObject_GC_NewVar (PyTypeObject * , int );
238
+ extern DL_IMPORT (void ) _PyObject_GC_Del (PyObject * );
239
+ extern DL_IMPORT (void ) _PyObject_GC_Track (PyObject * );
240
+ extern DL_IMPORT (void ) _PyObject_GC_UnTrack (PyObject * );
254
241
255
- /* Structure *prefixed* to container objects participating in GC */
242
+ /* GC information is stored BEFORE the object structure */
256
243
typedef struct _gc_head {
257
- struct _gc_head * gc_next ;
244
+ struct _gc_head * gc_next ; /* not NULL if object is tracked */
258
245
struct _gc_head * gc_prev ;
259
246
int gc_refs ;
260
247
} PyGC_Head ;
261
248
262
- #define PyGC_HEAD_SIZE sizeof(PyGC_Head)
249
+ extern PyGC_Head _PyGC_generation0 ;
250
+
251
+ /* Tell the GC to track this object. NB: While the object is tracked the
252
+ * collector it must be safe to call the ob_traverse method. */
253
+ #define _PyObject_GC_TRACK (o ) do { \
254
+ PyGC_Head *g = (PyGC_Head *)(o)-1; \
255
+ if (g->gc_next != NULL) \
256
+ Py_FatalError("GC object already in linked list"); \
257
+ g->gc_next = &_PyGC_generation0; \
258
+ g->gc_prev = _PyGC_generation0.gc_prev; \
259
+ g->gc_prev->gc_next = g; \
260
+ _PyGC_generation0.gc_prev = g; \
261
+ } while (0);
262
+
263
+ /* Tell the GC to stop tracking this object. */
264
+ #define _PyObject_GC_UNTRACK (o ) do { \
265
+ PyGC_Head *g = (PyGC_Head *)(o)-1; \
266
+ g->gc_prev->gc_next = g->gc_next; \
267
+ g->gc_next->gc_prev = g->gc_prev; \
268
+ g->gc_next = NULL; \
269
+ } while (0);
270
+
271
+ #define PyObject_GC_Track (op ) _PyObject_GC_Track((PyObject *)op)
272
+ #define PyObject_GC_UnTrack (op ) _PyObject_GC_UnTrack((PyObject *)op)
273
+
274
+
275
+ #define PyObject_GC_New (type , typeobj ) \
276
+ ( (type *) _PyObject_GC_New(typeobj) )
277
+ #define PyObject_GC_NewVar (type , typeobj , n ) \
278
+ ( (type *) _PyObject_GC_NewVar((typeobj), (n)) )
279
+ #define PyObject_GC_Del (op ) _PyObject_GC_Del((PyObject *)(op))
280
+
281
+ #else /* !WITH_CYCLE_GC */
282
+
283
+ #define PyObject_GC_New PyObject_New
284
+ #define PyObject_GC_NewVar PyObject_NewVar
285
+ #define PyObject_GC_Del PyObject_Del
286
+ #define PyObject_GC_TRACK (op )
287
+ #define PyObject_GC_UNTRACK (op )
288
+ #define PyObject_GC_Track (op )
289
+ #define PyObject_GC_UnTrack (op )
263
290
264
- /* Test if a type has a GC head */
265
- #define PyType_IS_GC (t ) PyType_HasFeature((t), Py_TPFLAGS_GC)
266
-
267
- /* Test if an object has a GC head */
268
- #define PyObject_IS_GC (o ) PyType_IS_GC((o)->ob_type)
269
-
270
- /* Get an object's GC head */
271
- #define PyObject_AS_GC (o ) ((PyGC_Head *)(o)-1)
272
-
273
- /* Get the object given the PyGC_Head */
274
- #define PyObject_FROM_GC (g ) ((PyObject *)(((PyGC_Head *)g)+1))
275
-
276
- /* Calculate tp_basicsize excluding PyGC_HEAD_SIZE if applicable */
277
- #define PyType_BASICSIZE (t ) (!PyType_IS_GC(t) ? (t)->tp_basicsize : \
278
- (t)->tp_basicsize - PyGC_HEAD_SIZE)
279
- #define PyType_SET_BASICSIZE (t , s ) (!PyType_IS_GC(t) ? \
280
- ((t)->tp_basicsize = (s)) : \
281
- ((t)->tp_basicsize = (s) + PyGC_HEAD_SIZE))
291
+ #endif
282
292
283
- extern DL_IMPORT (void ) _PyGC_Dump (PyGC_Head * );
293
+ /* This is here for the sake of backwards compatibility. Extensions that
294
+ * use the old GC API will still compile but the objects will not be
295
+ * tracked by the GC. */
296
+ #define PyGC_HEAD_SIZE 0
297
+ #define PyObject_GC_Init (op )
298
+ #define PyObject_GC_Fini (op )
299
+ #define PyObject_AS_GC (op ) (op)
300
+ #define PyObject_FROM_GC (op ) (op)
284
301
285
- #endif /* WITH_CYCLE_GC */
286
302
287
303
/* Test if a type supports weak references */
288
304
#define PyType_SUPPORTS_WEAKREFS (t ) \
0 commit comments