@@ -4975,10 +4975,10 @@ \section{Supporting Cyclic Garbarge Collection
49754975
49764976To create a container type, the \member {tp_flags} field of the type
49774977object must include the \constant {Py_TPFLAGS_GC} and provide an
4978- implementation of the \member {tp_traverse} handler. The value of the
4979- \member {tp_basicsize} field must include \constant {PyGC_HEAD_SIZE} as
4980- well. If instances of the type are mutable, a \member {tp_clear}
4981- implementation must also be provided.
4978+ implementation of the \member {tp_traverse} handler. The computed
4979+ value of the \member {tp_basicsize} field must include
4980+ \constant {PyGC_HEAD_SIZE} as well. If instances of the type are
4981+ mutable, a \member {tp_clear} implementation must also be provided.
49824982
49834983\begin {datadesc }{Py_TPFLAGS_GC}
49844984 Objects with a type with this flag set must conform with the rules
@@ -4992,6 +4992,17 @@ \section{Supporting Cyclic Garbarge Collection
49924992 collector is disabled at compile time then this is \code {0}.
49934993\end {datadesc }
49944994
4995+ Constructors for container types must conform to two rules:
4996+
4997+ \begin {enumerate }
4998+ \item The memory for the object must be allocated using
4999+ \cfunction {PyObject_New()} or \cfunction {PyObject_VarNew()}.
5000+
5001+ \item Once all the fields which may contain references to other
5002+ containers are initialized, it must call
5003+ \cfunction {PyObject_GC_Init()}.
5004+ \end {enumerate }
5005+
49955006\begin {cfuncdesc }{void}{PyObject_GC_Init}{PyObject *op}
49965007 Adds the object \var {op} to the set of container objects tracked by
49975008 the collector. The collector can run at unexpected times so objects
@@ -5000,6 +5011,17 @@ \section{Supporting Cyclic Garbarge Collection
50005011 usually near the end of the constructor.
50015012\end {cfuncdesc }
50025013
5014+ Similarly, the deallocator for the object must conform to a similar
5015+ pair of rules:
5016+
5017+ \begin {enumerate }
5018+ \item Before fields which refer to other containers are invalidated,
5019+ \cfunction {PyObject_GC_Fini()} must be called.
5020+
5021+ \item The object's memory must be deallocated using
5022+ \cfunction {PyObject_Del()}.
5023+ \end {enumerate }
5024+
50035025\begin {cfuncdesc }{void}{PyObject_GC_Fini}{PyObject *op}
50045026 Remove the object \var {op} from the set of container objects tracked
50055027 by the collector. Note that \cfunction {PyObject_GC_Init()} can be
@@ -5045,6 +5067,106 @@ \section{Supporting Cyclic Garbarge Collection
50455067\end {ctypedesc }
50465068
50475069
5070+ \subsection {Example Cycle Collector Support
5071+ \label {example-cycle-support } }
5072+
5073+ This example shows only enough of the implementation of an extension
5074+ type to show how the garbage collector support needs to be added. It
5075+ shows the definition of the object structure, the
5076+ \member {tp_traverse}, \member {tp_clear} and \member {tp_dealloc}
5077+ implementations, the type structure, and a constructor --- the module
5078+ initialization needed to export the constructor to Python is not shown
5079+ as there are no special considerations there for the collector. To
5080+ make this interesting, assume that the module exposes ways for the
5081+ \member {container} field of the object to be modified. Note that
5082+ since no checks are made on the type of the object used to initialize
5083+ \member {container}, we have to assume that it may be a container.
5084+
5085+ \begin {verbatim }
5086+ #include "Python.h"
5087+
5088+ typedef struct {
5089+ PyObject_HEAD
5090+ PyObject *container;
5091+ } MyObject;
5092+
5093+ static int
5094+ my_traverse(MyObject *self, visitproc visit, void *arg)
5095+ {
5096+ if (self->container != NULL)
5097+ return visit(self->container, arg);
5098+ else
5099+ return 0;
5100+ }
5101+
5102+ static int
5103+ my_clear(MyObject *self)
5104+ {
5105+ Py_XDECREF(self->container);
5106+ self->container = NULL;
5107+
5108+ return 0;
5109+ }
5110+
5111+ static void
5112+ my_dealloc(MyObject *self)
5113+ {
5114+ PyObject_GC_Fini((PyObject *) self);
5115+ Py_XDECREF(self->container);
5116+ PyObject_Del(self);
5117+ }
5118+ \end {verbatim }
5119+
5120+ \begin {verbatim }
5121+ statichere PyTypeObject
5122+ MyObject_Type = {
5123+ PyObject_HEAD_INIT(NULL)
5124+ 0,
5125+ "MyObject",
5126+ sizeof(MyObject) + PyGC_HEAD_SIZE,
5127+ 0,
5128+ (destructor)my_dealloc, /* tp_dealloc */
5129+ 0, /* tp_print */
5130+ 0, /* tp_getattr */
5131+ 0, /* tp_setattr */
5132+ 0, /* tp_compare */
5133+ 0, /* tp_repr */
5134+ 0, /* tp_as_number */
5135+ 0, /* tp_as_sequence */
5136+ 0, /* tp_as_mapping */
5137+ 0, /* tp_hash */
5138+ 0, /* tp_call */
5139+ 0, /* tp_str */
5140+ 0, /* tp_getattro */
5141+ 0, /* tp_setattro */
5142+ 0, /* tp_as_buffer */
5143+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,
5144+ 0, /* tp_doc */
5145+ (traverseproc)my_traverse, /* tp_traverse */
5146+ (inquiry)my_clear, /* tp_clear */
5147+ 0, /* tp_richcompare */
5148+ 0, /* tp_weaklistoffset */
5149+ };
5150+
5151+ /* This constructor should be made accessible from Python. */
5152+ static PyObject *
5153+ new_object(PyObject *unused, PyObject *args)
5154+ {
5155+ PyObject *container = NULL;
5156+ MyObject *result = NULL;
5157+
5158+ if (PyArg_ParseTuple(args, "|O:new_object", &container)) {
5159+ result = PyObject_New(MyObject, &MyObject_Type);
5160+ if (result != NULL) {
5161+ result->container = container;
5162+ PyObject_GC_Init();
5163+ }
5164+ }
5165+ return (PyObject *) result;
5166+ }
5167+ \end {verbatim }
5168+
5169+
50485170% \chapter{Debugging \label{debugging}}
50495171%
50505172% XXX Explain Py_DEBUG, Py_TRACE_REFS, Py_REF_DEBUG.
0 commit comments