blob: 8e495e63ba42e52e1ebb15ba40de3d915f487fe6 [file] [log] [blame]
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +00001/*
2
3 Reference Cycle Garbage Collection
4 ==================================
5
6 Neil Schemenauer <nascheme@enme.ucalgary.ca>
7
8 Based on a post on the python-dev list. Ideas from Guido van Rossum,
9 Eric Tiedemann, and various others.
10
11 http://www.enme.calgary.ca/~nascheme/python/gc.html
12 http://www.python.org/pipermail/python-dev/2000-March/003869.html
13 http://www.python.org/pipermail/python-dev/2000-March/004010.html
14 http://www.python.org/pipermail/python-dev/2000-March/004022.html
15
16 For a highlevel view of the collection process, read the collect
17 function.
18
19 TODO:
20 use a different interface for set_debug() (keywords)?
21 tune parameters
22
23*/
24
25
26#include "Python.h"
27
28#ifdef WITH_CYCLE_GC
29
30/* magic gc_refs value */
31#define GC_MOVED -1
32
33/*** Global GC state ***/
34
35/* linked lists of container objects */
36static PyGC_Head generation0 = {&generation0, &generation0, 0};
37static PyGC_Head generation1 = {&generation1, &generation1, 0};
38static PyGC_Head generation2 = {&generation2, &generation2, 0};
39static int generation = 0; /* current generation being collected */
40
41/* collection frequencies, XXX tune these */
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +000042static int enabled = 1; /* automatic collection enabled? */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +000043static int threshold0 = 100; /* net new containers before collection */
44static int threshold1 = 10; /* generation0 collections before collecting 1 */
45static int threshold2 = 10; /* generation1 collections before collecting 2 */
46
47/* net new objects allocated since last collection */
48static int allocated;
49
50/* set for debugging information */
51#define DEBUG_STATS (1<<0) /* print collection statistics */
52#define DEBUG_COLLECTABLE (1<<1) /* print collectable objects */
53#define DEBUG_UNCOLLECTABLE (1<<2) /* print uncollectable objects */
54#define DEBUG_INSTANCES (1<<3) /* print instances */
55#define DEBUG_OBJECTS (1<<4) /* print other objects */
56#define DEBUG_LEAK DEBUG_COLLECTABLE | \
57 DEBUG_UNCOLLECTABLE | \
58 DEBUG_INSTANCES | \
59 DEBUG_OBJECTS
60static int debug;
61
62/* list of uncollectable objects */
63static PyObject *garbage;
64
65
66/*** list functions ***/
67
68static void
69gc_list_init(PyGC_Head *list)
70{
71 list->gc_prev = list;
72 list->gc_next = list;
73}
74
75static void
76gc_list_append(PyGC_Head *node, PyGC_Head *list)
77{
78 node->gc_next = list;
79 node->gc_prev = list->gc_prev;
80 node->gc_prev->gc_next = node;
81 list->gc_prev = node;
82}
83
84static void
85gc_list_remove(PyGC_Head *node)
86{
87 node->gc_prev->gc_next = node->gc_next;
88 node->gc_next->gc_prev = node->gc_prev;
89#ifdef Py_DEBUG
90 node->gc_prev = NULL;
91 node->gc_next = NULL;
92#endif
93}
94
95static void
96gc_list_move(PyGC_Head *from, PyGC_Head *to)
97{
98 if (from->gc_next == from) {
99 /* empty from list */
100 gc_list_init(to);
101 } else {
102 to->gc_next = from->gc_next;
103 to->gc_next->gc_prev = to;
104 to->gc_prev = from->gc_prev;
105 to->gc_prev->gc_next = to;
106 }
107 gc_list_init(from);
108}
109
110/* append a list onto another list, from becomes an empty list */
111static void
112gc_list_merge(PyGC_Head *from, PyGC_Head *to)
113{
114 PyGC_Head *tail;
115 if (from->gc_next != from) {
116 tail = to->gc_prev;
117 tail->gc_next = from->gc_next;
118 tail->gc_next->gc_prev = tail;
119 to->gc_prev = from->gc_prev;
120 to->gc_prev->gc_next = to;
121 }
122 gc_list_init(from);
123}
124
125static long
126gc_list_size(PyGC_Head *list)
127{
128 PyGC_Head *gc;
129 long n = 0;
130 for (gc = list->gc_next; gc != list; gc = gc->gc_next) {
131 n++;
132 }
133 return n;
134}
135
136/*** end of list stuff ***/
137
138
139/* Set all gc_refs = ob_refcnt */
140static void
141update_refs(PyGC_Head *containers)
142{
143 PyGC_Head *gc = containers->gc_next;
144 for (; gc != containers; gc=gc->gc_next) {
145 gc->gc_refs = PyObject_FROM_GC(gc)->ob_refcnt;
146 }
147}
148
149static int
150visit_decref(PyObject *op, void *data)
151{
152 if (op && PyObject_IS_GC(op)) {
153 PyObject_AS_GC(op)->gc_refs--;
154 }
155 return 0;
156}
157
158/* Subtract internal references from gc_refs */
159static void
160subtract_refs(PyGC_Head *containers)
161{
162 traverseproc traverse;
163 PyGC_Head *gc = containers->gc_next;
164 for (; gc != containers; gc=gc->gc_next) {
165 traverse = PyObject_FROM_GC(gc)->ob_type->tp_traverse;
166 (void) traverse(PyObject_FROM_GC(gc),
167 (visitproc)visit_decref,
168 NULL);
169 }
170}
171
172/* Append objects with gc_refs > 0 to roots list */
173static void
174move_roots(PyGC_Head *containers, PyGC_Head *roots)
175{
176 PyGC_Head *next;
177 PyGC_Head *gc = containers->gc_next;
178 while (gc != containers) {
179 next = gc->gc_next;
180 if (gc->gc_refs > 0) {
181 gc_list_remove(gc);
182 gc_list_append(gc, roots);
183 gc->gc_refs = GC_MOVED;
184 }
185 gc = next;
186 }
187}
188
189static int
190visit_reachable(PyObject *op, PyGC_Head *roots)
191{
192 if (PyObject_IS_GC(op)) {
193 PyGC_Head *gc = PyObject_AS_GC(op);
194 if (gc && gc->gc_refs != GC_MOVED) {
195 gc_list_remove(gc);
196 gc_list_append(gc, roots);
197 gc->gc_refs = GC_MOVED;
198 }
199 }
200 return 0;
201}
202
203/* Move objects referenced from reachable to reachable set. */
204static void
205move_root_reachable(PyGC_Head *reachable)
206{
207 traverseproc traverse;
208 PyGC_Head *gc = reachable->gc_next;
209 for (; gc != reachable; gc=gc->gc_next) {
210 /* careful, reachable list is growing here */
211 PyObject *op = PyObject_FROM_GC(gc);
212 traverse = op->ob_type->tp_traverse;
213 (void) traverse(op,
214 (visitproc)visit_reachable,
215 (void *)reachable);
216 }
217}
218
219/* move all objects with finalizers (instances with __del__) */
220static void
221move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
222{
223 PyGC_Head *next;
224 PyGC_Head *gc = unreachable->gc_next;
225 static PyObject *delstr;
226 if (delstr == NULL) {
227 delstr = PyString_InternFromString("__del__");
228 }
229 for (; gc != unreachable; gc=next) {
230 PyObject *op = PyObject_FROM_GC(gc);
231 next = gc->gc_next;
232 if (PyInstance_Check(op) && PyObject_HasAttr(op, delstr)) {
233 gc_list_remove(gc);
234 gc_list_append(gc, finalizers);
235 }
236 }
237}
238
239
240/* called by tp_traverse */
241static int
242visit_finalizer_reachable(PyObject *op, PyGC_Head *finalizers)
243{
244 if (PyObject_IS_GC(op)) {
245 PyGC_Head *gc = PyObject_AS_GC(op);
246 if (gc && gc->gc_refs != GC_MOVED) {
247 gc_list_remove(gc);
248 gc_list_append(gc, finalizers);
249 gc->gc_refs = GC_MOVED;
250 }
251 }
252 return 0;
253}
254
255/* Move objects referenced from roots to roots */
256static void
257move_finalizer_reachable(PyGC_Head *finalizers)
258{
259 traverseproc traverse;
260 PyGC_Head *gc = finalizers->gc_next;
261 for (; gc != finalizers; gc=gc->gc_next) {
262 /* careful, finalizers list is growing here */
263 traverse = PyObject_FROM_GC(gc)->ob_type->tp_traverse;
264 (void) traverse(PyObject_FROM_GC(gc),
265 (visitproc)visit_finalizer_reachable,
266 (void *)finalizers);
267 }
268}
269
270static void
271debug_instance(PyObject *output, char *msg, PyInstanceObject *inst)
272{
273 char buf[200];
274 char *cname;
275 /* be careful not to create new dictionaries */
276 PyObject *classname = inst->in_class->cl_name;
277 if (classname != NULL && PyString_Check(classname))
278 cname = PyString_AsString(classname);
279 else
280 cname = "?";
Barry Warsaw35e459c2000-07-12 05:18:36 +0000281 sprintf(buf, "gc: %s<%.100s instance at %p>\n", msg, cname, inst);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000282 PyFile_WriteString(buf, output);
283}
284
285static void
286debug_cycle(PyObject *output, char *msg, PyObject *op)
287{
288 if ((debug & DEBUG_INSTANCES) && PyInstance_Check(op)) {
289 debug_instance(output, msg, (PyInstanceObject *)op);
290 } else if (debug & DEBUG_OBJECTS) {
291 char buf[200];
Barry Warsaw35e459c2000-07-12 05:18:36 +0000292 sprintf(buf, "gc: %s<%.100s %p>\n", msg,
293 op->ob_type->tp_name, op);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000294 PyFile_WriteString(buf, output);
295 }
296}
297
298/* Handle uncollectable garbage (cycles with finalizers). */
299static void
300handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
301{
302 PyGC_Head *gc;
303 if (garbage == NULL) {
304 garbage = PyList_New(0);
305 }
306 for (gc = finalizers->gc_next; gc != finalizers;
307 gc = finalizers->gc_next) {
308 PyObject *op = PyObject_FROM_GC(gc);
309 /* Add all instances to a Python accessible list of garbage */
310 if (PyInstance_Check(op)) {
311 PyList_Append(garbage, op);
312 }
313 /* We assume that all objects in finalizers are reachable from
314 * instances. Once we add the instances to the garbage list
315 * everything is reachable from Python again. */
316 gc_list_remove(gc);
317 gc_list_append(gc, old);
318 }
319}
320
321/* Break reference cycles by clearing the containers involved. This is
322 * tricky business as the lists can be changing and we don't know which
323 * objects may be freed. It is possible I screwed something up here. */
324static void
325delete_garbage(PyGC_Head *unreachable, PyGC_Head *old)
326{
327 inquiry clear;
328
329 while (unreachable->gc_next != unreachable) {
330 PyGC_Head *gc = unreachable->gc_next;
331 PyObject *op = PyObject_FROM_GC(gc);
332 /*
333 PyList_Append(garbage, op);
334 */
335 if ((clear = op->ob_type->tp_clear) != NULL) {
336 Py_INCREF(op);
337 clear((PyObject *)op);
338 Py_DECREF(op);
339 }
340 /* only try to call tp_clear once for each object */
341 if (unreachable->gc_next == gc) {
342 /* still alive, move it, it may die later */
343 gc_list_remove(gc);
344 gc_list_append(gc, old);
345 }
346 }
347}
348
349/* This is the main function. Read this to understand how the
350 * collection process works. */
351static long
352collect(PyGC_Head *young, PyGC_Head *old)
353{
354 long n = 0;
355 long m = 0;
356 PyGC_Head reachable;
357 PyGC_Head unreachable;
358 PyGC_Head finalizers;
359 PyGC_Head *gc;
360 PyObject *output = NULL;
361
362 if (debug) {
363 output = PySys_GetObject("stderr");
364 }
365 if (debug & DEBUG_STATS) {
366 char buf[100];
367 sprintf(buf, "gc: collecting generation %d...\n", generation);
368 PyFile_WriteString(buf,output);
Fred Drakeb35de5b2000-07-11 14:37:41 +0000369 sprintf(buf, "gc: objects in each generation: %ld %ld %ld\n",
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000370 gc_list_size(&generation0),
371 gc_list_size(&generation1),
372 gc_list_size(&generation2));
373 PyFile_WriteString(buf,output);
374 }
375
376 /* Using ob_refcnt and gc_refs, calculate which objects in the
377 * container set are reachable from outside the set (ie. have a
378 * refcount greater than 0 when all the references within the
379 * set are taken into account */
380 update_refs(young);
381 subtract_refs(young);
382
383 /* Move everything reachable from outside the set into the
384 * reachable set (ie. gc_refs > 0). Next, move everything
385 * reachable from objects in the reachable set. */
386 gc_list_init(&reachable);
387 move_roots(young, &reachable);
388 move_root_reachable(&reachable);
389
390 /* move unreachable objects to a temporary list, new objects can be
391 * allocated after this point */
392 gc_list_init(&unreachable);
393 gc_list_move(young, &unreachable);
394
395 /* move reachable objects to next generation */
396 gc_list_merge(&reachable, old);
397
398 /* Move objects reachable from finalizers, we can't safely delete
399 * them. Python programmers should take care not to create such
400 * things. For Python finalizers means instance objects with
401 * __del__ methods. */
402 gc_list_init(&finalizers);
403 move_finalizers(&unreachable, &finalizers);
404 move_finalizer_reachable(&finalizers);
405
406 /* Collect statistics on collectable objects found and print
407 * debugging information. */
408 for (gc = unreachable.gc_next; gc != &unreachable;
409 gc = gc->gc_next) {
410 m++;
411 if (output != NULL && (debug & DEBUG_COLLECTABLE)) {
412 debug_cycle(output, "collectable ", PyObject_FROM_GC(gc));
413 }
414 }
415 /* call tp_clear on objects in the collectable set. This will cause
416 * the reference cycles to be broken. It may also cause some objects in
417 * finalizers to be freed */
418 delete_garbage(&unreachable, old);
419
420 /* Collect statistics on uncollectable objects found and print
421 * debugging information. */
422 for (gc = finalizers.gc_next; gc != &finalizers;
423 gc = gc->gc_next) {
424 n++;
425 if (output != NULL && (debug & DEBUG_UNCOLLECTABLE)) {
426 debug_cycle(output, "uncollectable ", PyObject_FROM_GC(gc));
427 }
428 }
429 if (output != NULL && (debug & DEBUG_STATS)) {
430 if (m == 0 && n == 0) {
431 PyFile_WriteString("gc: done.\n", output);
432 } else {
433 char buf[200];
434 sprintf(buf,
Fred Drakeb35de5b2000-07-11 14:37:41 +0000435 "gc: done, %ld unreachable, %ld uncollectable.\n",
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000436 n+m, n);
437 PyFile_WriteString(buf, output);
438 }
439 }
440
441 /* Append instances in the uncollectable set to a Python
442 * reachable list of garbage. The programmer has to deal with
443 * this if they insist on creating this type of structure. */
444 handle_finalizers(&finalizers, old);
445
446 allocated = 0;
447 PyErr_Clear(); /* in case writing to sys.stderr failed */
448 return n+m;
449}
450
451static long
452collect_generations(void)
453{
454 static long collections0 = 0;
455 static long collections1 = 0;
Vladimir Marangozovb16714b2000-07-10 05:37:39 +0000456 long n = 0;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000457
458
459 if (collections1 > threshold2) {
460 generation = 2;
461 gc_list_merge(&generation0, &generation2);
462 gc_list_merge(&generation1, &generation2);
463 if (generation2.gc_next != &generation2) {
464 n = collect(&generation2, &generation2);
465 }
466 collections1 = 0;
467 } else if (collections0 > threshold1) {
468 generation = 1;
469 collections1++;
470 gc_list_merge(&generation0, &generation1);
471 if (generation1.gc_next != &generation1) {
472 n = collect(&generation1, &generation2);
473 }
474 collections0 = 0;
475 } else {
476 generation = 0;
477 collections0++;
478 if (generation0.gc_next != &generation0) {
479 n = collect(&generation0, &generation1);
480 }
481 }
482 return n;
483}
484
485void
486_PyGC_Insert(PyObject *op)
487{
488 /* collection lock since collecting may cause allocations */
489 static int collecting = 0;
490
491#ifdef Py_DEBUG
492 if (!PyObject_IS_GC(op)) {
493 abort();
494 }
495#endif
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000496 if (allocated > threshold0 && enabled && threshold0 && !collecting) {
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000497 collecting++;
498 collect_generations();
499 collecting--;
500 }
501 allocated++;
502 gc_list_append(PyObject_AS_GC(op), &generation0);
503}
504
505void
506_PyGC_Remove(PyObject *op)
507{
508 PyGC_Head *g = PyObject_AS_GC(op);
509#ifdef Py_DEBUG
510 if (!PyObject_IS_GC(op)) {
511 abort();
512 }
513#endif
514 gc_list_remove(g);
515 if (allocated > 0) {
516 allocated--;
517 }
518}
519
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000520static char gc_enable__doc__[] =
521"enable() -> None\n"
522"\n"
523"Enable automatic garbage collection.\n"
524;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000525
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000526static PyObject *
527gc_enable(PyObject *self, PyObject *args)
528{
529
530 if (!PyArg_ParseTuple(args, ":enable")) /* check no args */
531 return NULL;
532
533 enabled = 1;
534
535 Py_INCREF(Py_None);
536 return Py_None;
537}
538
539static char gc_disable__doc__[] =
540"disable() -> None\n"
541"\n"
542"Disable automatic garbage collection.\n"
543;
544
545static PyObject *
546gc_disable(PyObject *self, PyObject *args)
547{
548
549 if (!PyArg_ParseTuple(args, ":disable")) /* check no args */
550 return NULL;
551
552 enabled = 0;
553
554 Py_INCREF(Py_None);
555 return Py_None;
556}
557
558static char gc_isenabled__doc__[] =
559"isenabled() -> status\n"
560"\n"
561"Returns true if automatic garbage collection is enabled.\n"
562;
563
564static PyObject *
565gc_isenabled(PyObject *self, PyObject *args)
566{
567
568 if (!PyArg_ParseTuple(args, ":isenabled")) /* check no args */
569 return NULL;
570
571 return Py_BuildValue("i", enabled);
572}
573
574static char gc_collect__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000575"collect() -> n\n"
576"\n"
577"Run a full collection. The number of unreachable objects is returned.\n"
578;
579
580static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000581gc_collect(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000582{
583 long n;
584
Fred Drakecc1be242000-07-12 04:42:23 +0000585 if (!PyArg_ParseTuple(args, ":collect")) /* check no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000586 return NULL;
587
588 generation = 2;
589 gc_list_merge(&generation0, &generation2);
590 gc_list_merge(&generation1, &generation2);
591 n = collect(&generation2, &generation2);
592
593 return Py_BuildValue("i", n);
594}
595
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000596static char gc_set_debug__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000597"set_debug(flags) -> None\n"
598"\n"
599"Set the garbage collection debugging flags. Debugging information is\n"
600"written to sys.stderr.\n"
601"\n"
602"flags is an integer and can have the following bits turned on:\n"
603"\n"
604" DEBUG_STATS - Print statistics during collection.\n"
605" DEBUG_COLLECTABLE - Print collectable objects found.\n"
606" DEBUG_UNCOLLECTABLE - Print unreachable but uncollectable objects found.\n"
607" DEBUG_INSTANCES - Print instance objects.\n"
608" DEBUG_OBJECTS - Print objects other than instances.\n"
609" DEBUG_LEAK - Debug leaking programs (everything but STATS).\n"
610;
611
612static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000613gc_set_debug(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000614{
Fred Drakecc1be242000-07-12 04:42:23 +0000615 if (!PyArg_ParseTuple(args, "l:get_debug", &debug))
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000616 return NULL;
617
618 Py_INCREF(Py_None);
619 return Py_None;
620}
621
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000622static char gc_get_debug__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000623"get_debug() -> flags\n"
624"\n"
625"Get the garbage collection debugging flags.\n"
626;
627
628static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000629gc_get_debug(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000630{
Fred Drakecc1be242000-07-12 04:42:23 +0000631 if (!PyArg_ParseTuple(args, ":get_debug")) /* no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000632 return NULL;
633
634 return Py_BuildValue("i", debug);
635}
636
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000637static char gc_set_thresh__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000638"set_threshold(threshold0, [threhold1, threshold2]) -> None\n"
639"\n"
640"Sets the collection thresholds. Setting threshold0 to zero disables\n"
641"collection.\n"
642;
643
644static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000645gc_set_thresh(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000646{
Fred Drakecc1be242000-07-12 04:42:23 +0000647 if (!PyArg_ParseTuple(args, "i|ii:set_threshold", &threshold0,
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000648 &threshold1, &threshold2))
649 return NULL;
650
651 Py_INCREF(Py_None);
652 return Py_None;
653}
654
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000655static char gc_get_thresh__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000656"get_threshold() -> (threshold0, threshold1, threshold2)\n"
657"\n"
658"Return the current collection thresholds\n"
659;
660
661static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000662gc_get_thresh(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000663{
Fred Drakecc1be242000-07-12 04:42:23 +0000664 if (!PyArg_ParseTuple(args, ":get_threshold")) /* no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000665 return NULL;
666
667 return Py_BuildValue("(iii)", threshold0, threshold1, threshold2);
668}
669
670
671static char gc__doc__ [] =
672"This module provides access to the garbage collector for reference cycles.\n"
673"\n"
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000674"enable() -- Enable automatic garbage collection.\n"
675"disable() -- Disable automatic garbage collection.\n"
676"isenabled() -- Returns true if automatic collection is enabled.\n"
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000677"collect() -- Do a full collection right now.\n"
678"set_debug() -- Set debugging flags.\n"
679"get_debug() -- Get debugging flags.\n"
680"set_threshold() -- Set the collection thresholds.\n"
681"get_threshold() -- Return the current the collection thresholds.\n"
682;
683
684static PyMethodDef GcMethods[] = {
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000685 {"enable", gc_enable, METH_VARARGS, gc_enable__doc__},
686 {"disable", gc_disable, METH_VARARGS, gc_disable__doc__},
687 {"isenabled", gc_isenabled, METH_VARARGS, gc_isenabled__doc__},
688 {"set_debug", gc_set_debug, METH_VARARGS, gc_set_debug__doc__},
689 {"get_debug", gc_get_debug, METH_VARARGS, gc_get_debug__doc__},
690 {"set_threshold", gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__},
691 {"get_threshold", gc_get_thresh, METH_VARARGS, gc_get_thresh__doc__},
692 {"collect", gc_collect, METH_VARARGS, gc_collect__doc__},
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000693 {NULL, NULL} /* Sentinel */
694};
695
696void
697initgc(void)
698{
699 PyObject *m;
700 PyObject *d;
701
702 m = Py_InitModule4("gc",
703 GcMethods,
704 gc__doc__,
705 NULL,
706 PYTHON_API_VERSION);
707 d = PyModule_GetDict(m);
708 if (garbage == NULL) {
709 garbage = PyList_New(0);
710 }
711 PyDict_SetItemString(d, "garbage", garbage);
712 PyDict_SetItemString(d, "DEBUG_STATS",
713 PyInt_FromLong(DEBUG_STATS));
714 PyDict_SetItemString(d, "DEBUG_COLLECTABLE",
715 PyInt_FromLong(DEBUG_COLLECTABLE));
716 PyDict_SetItemString(d, "DEBUG_UNCOLLECTABLE",
717 PyInt_FromLong(DEBUG_UNCOLLECTABLE));
718 PyDict_SetItemString(d, "DEBUG_INSTANCES",
719 PyInt_FromLong(DEBUG_INSTANCES));
720 PyDict_SetItemString(d, "DEBUG_OBJECTS",
721 PyInt_FromLong(DEBUG_OBJECTS));
722 PyDict_SetItemString(d, "DEBUG_LEAK",
723 PyInt_FromLong(DEBUG_LEAK));
724}
725
726#endif /* WITH_CYCLE_GC */