[Patches] GC patch 3 and 4
Vladimir Marangozov
Vladimir.Marangozov@inrialpes.fr
Wed, 28 Jun 2000 03:02:07 +0200 (CEST)
I'm concerned about the following with these patches:
1. The PyObject_GC API
This is related with #2 below.
As it was discussed previously, PyObject_GC_NEW is useless. I think
that the same applies to PyObject_GC_DEL - we don't need it.
I'd suggest to officialize the following API -- better names are welcome:
PyObject_FROM_GC(gp) - returns a pointer to a Python object given a
pointer to a GC_INFO struct. This is the current
PyGC_INFO macro.
PyObject_AS_GC(op) - returns a pointer to a GC_INFO struct given an
object pointer. This is the reverse macro
(the current PyGC_OBJ macro)
PyObject_GC_Init(op) - init an object for GC (usually, at the end of the
constructor, cf. comments in objimpl.h)
PyObject_GC_Fini(op) - finalize an object subject to GC (usually, in the
beginning of the destructor, cf. objimpl.h)
BTW, I'd really prefer a more Pythonic name for GC_INFO, like GC_HEAD
as per Greg Stein's comments on these patches.
2. Extension types that participate in GC
The GC code implemented in the (core) object constructors is #ifdef'ed
which is not what one is expected to do for custom extension types.
If I am about to implement a GC'd type with the proposed patches, I'll
have to #ifdef things which is not really what I want.
GC or not, I'd prefer to see the same code in the object constructors
and destructors (be they core or extension objects).
PyObject_GC_Init/Fini are fine. They are empty macros without GC,
so why not using the same approach for the inlined #ifdef'ed code?
For example, the PyList_New code reads:
...
if (op == NULL) {
return PyErr_NoMemory();
}
#ifdef WITH_CYCLE_GC
op = (PyListObject *) PyGC_OBJ((PyGCInfo *)op);
#endif
...
I'd expect to see something like this instead:
...
if (op == NULL) {
return PyErr_NoMemory();
}
op = (PyListObject *) PyObject_FROM_GC(op);
...
where:
#ifdef WITH_CYCLE_GC
#define PyObject_FROM_GC(gp) PyGC_INFO((PyGCInfo *)(gp))
#else
#define PyObject_FROM_GC(gp) (gp)
#endif
The same goes for the object destructors, where PyObject_GC_DEL(op)
would be replaced by: op = PyObject_AS_GC(op); PyObject_DEL(op)
Neil Schemenauer wrote:
[snip]
>
> + /*
> + * Garbage Collection Support
> + * ==========================
> + */
>
> + /* To make a new object participate in garbage collection use
> + PyObject_{New, VarNew, Del} to manage the memory. Set the type flag
^^^^^^
NewVar
> + Py_TPFLAGS_GC and define the type method tp_recurse. You should also
> + add the method tp_clear if your object is mutable. Include
> + PyGC_INFO_SIZE in the calculation of tp_basicsize. Call
> + PyObject_GC_Init after the pointers followed by tp_recurse become
> + valid (usually just before returning the object from the allocation
> + method. Call PyObject_GC_Fini before those pointers become invalid
> + (usually at the top of the deallocation method). */
>
[snip]
--
Vladimir MARANGOZOV | Vladimir.Marangozov@inrialpes.fr
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252