blob: 06f51ed6cd7c723dc68272809da8cc380b919c49 [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 Hylton3263dc2b2000-09-05 15:44:50 +000043static int threshold0 = 700; /* net new containers before collection */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +000044static 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
Jeremy Hyltonb709df32000-09-01 02:47:25 +000060static int debug;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +000061
62/* list of uncollectable objects */
63static PyObject *garbage;
64
Jeremy Hyltonb709df32000-09-01 02:47:25 +000065/* Python string to use if unhandled exception occurs */
66static PyObject *gc_str;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +000067
68/*** list functions ***/
69
70static void
71gc_list_init(PyGC_Head *list)
72{
73 list->gc_prev = list;
74 list->gc_next = list;
75}
76
77static void
78gc_list_append(PyGC_Head *node, PyGC_Head *list)
79{
80 node->gc_next = list;
81 node->gc_prev = list->gc_prev;
82 node->gc_prev->gc_next = node;
83 list->gc_prev = node;
84}
85
86static void
87gc_list_remove(PyGC_Head *node)
88{
89 node->gc_prev->gc_next = node->gc_next;
90 node->gc_next->gc_prev = node->gc_prev;
91#ifdef Py_DEBUG
92 node->gc_prev = NULL;
93 node->gc_next = NULL;
94#endif
95}
96
97static void
98gc_list_move(PyGC_Head *from, PyGC_Head *to)
99{
100 if (from->gc_next == from) {
101 /* empty from list */
102 gc_list_init(to);
103 } else {
104 to->gc_next = from->gc_next;
105 to->gc_next->gc_prev = to;
106 to->gc_prev = from->gc_prev;
107 to->gc_prev->gc_next = to;
108 }
109 gc_list_init(from);
110}
111
112/* append a list onto another list, from becomes an empty list */
113static void
114gc_list_merge(PyGC_Head *from, PyGC_Head *to)
115{
116 PyGC_Head *tail;
117 if (from->gc_next != from) {
118 tail = to->gc_prev;
119 tail->gc_next = from->gc_next;
120 tail->gc_next->gc_prev = tail;
121 to->gc_prev = from->gc_prev;
122 to->gc_prev->gc_next = to;
123 }
124 gc_list_init(from);
125}
126
127static long
128gc_list_size(PyGC_Head *list)
129{
130 PyGC_Head *gc;
131 long n = 0;
132 for (gc = list->gc_next; gc != list; gc = gc->gc_next) {
133 n++;
134 }
135 return n;
136}
137
138/*** end of list stuff ***/
139
140
141/* Set all gc_refs = ob_refcnt */
142static void
143update_refs(PyGC_Head *containers)
144{
145 PyGC_Head *gc = containers->gc_next;
146 for (; gc != containers; gc=gc->gc_next) {
147 gc->gc_refs = PyObject_FROM_GC(gc)->ob_refcnt;
148 }
149}
150
151static int
152visit_decref(PyObject *op, void *data)
153{
154 if (op && PyObject_IS_GC(op)) {
155 PyObject_AS_GC(op)->gc_refs--;
156 }
157 return 0;
158}
159
160/* Subtract internal references from gc_refs */
161static void
162subtract_refs(PyGC_Head *containers)
163{
164 traverseproc traverse;
165 PyGC_Head *gc = containers->gc_next;
166 for (; gc != containers; gc=gc->gc_next) {
167 traverse = PyObject_FROM_GC(gc)->ob_type->tp_traverse;
168 (void) traverse(PyObject_FROM_GC(gc),
169 (visitproc)visit_decref,
170 NULL);
171 }
172}
173
174/* Append objects with gc_refs > 0 to roots list */
175static void
176move_roots(PyGC_Head *containers, PyGC_Head *roots)
177{
178 PyGC_Head *next;
179 PyGC_Head *gc = containers->gc_next;
180 while (gc != containers) {
181 next = gc->gc_next;
182 if (gc->gc_refs > 0) {
183 gc_list_remove(gc);
184 gc_list_append(gc, roots);
185 gc->gc_refs = GC_MOVED;
186 }
187 gc = next;
188 }
189}
190
191static int
192visit_reachable(PyObject *op, PyGC_Head *roots)
193{
194 if (PyObject_IS_GC(op)) {
195 PyGC_Head *gc = PyObject_AS_GC(op);
196 if (gc && gc->gc_refs != GC_MOVED) {
197 gc_list_remove(gc);
198 gc_list_append(gc, roots);
199 gc->gc_refs = GC_MOVED;
200 }
201 }
202 return 0;
203}
204
205/* Move objects referenced from reachable to reachable set. */
206static void
207move_root_reachable(PyGC_Head *reachable)
208{
209 traverseproc traverse;
210 PyGC_Head *gc = reachable->gc_next;
211 for (; gc != reachable; gc=gc->gc_next) {
212 /* careful, reachable list is growing here */
213 PyObject *op = PyObject_FROM_GC(gc);
214 traverse = op->ob_type->tp_traverse;
215 (void) traverse(op,
216 (visitproc)visit_reachable,
217 (void *)reachable);
218 }
219}
220
221/* move all objects with finalizers (instances with __del__) */
222static void
223move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
224{
225 PyGC_Head *next;
226 PyGC_Head *gc = unreachable->gc_next;
Jeremy Hylton06257772000-08-31 15:10:24 +0000227 static PyObject *delstr = NULL;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000228 if (delstr == NULL) {
229 delstr = PyString_InternFromString("__del__");
Jeremy Hylton06257772000-08-31 15:10:24 +0000230 if (delstr == NULL)
231 Py_FatalError("PyGC: can't initialize __del__ string");
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000232 }
233 for (; gc != unreachable; gc=next) {
234 PyObject *op = PyObject_FROM_GC(gc);
235 next = gc->gc_next;
236 if (PyInstance_Check(op) && PyObject_HasAttr(op, delstr)) {
237 gc_list_remove(gc);
238 gc_list_append(gc, finalizers);
239 }
240 }
241}
242
243
244/* called by tp_traverse */
245static int
246visit_finalizer_reachable(PyObject *op, PyGC_Head *finalizers)
247{
248 if (PyObject_IS_GC(op)) {
249 PyGC_Head *gc = PyObject_AS_GC(op);
250 if (gc && gc->gc_refs != GC_MOVED) {
251 gc_list_remove(gc);
252 gc_list_append(gc, finalizers);
253 gc->gc_refs = GC_MOVED;
254 }
255 }
256 return 0;
257}
258
259/* Move objects referenced from roots to roots */
260static void
261move_finalizer_reachable(PyGC_Head *finalizers)
262{
263 traverseproc traverse;
264 PyGC_Head *gc = finalizers->gc_next;
265 for (; gc != finalizers; gc=gc->gc_next) {
266 /* careful, finalizers list is growing here */
267 traverse = PyObject_FROM_GC(gc)->ob_type->tp_traverse;
268 (void) traverse(PyObject_FROM_GC(gc),
269 (visitproc)visit_finalizer_reachable,
270 (void *)finalizers);
271 }
272}
273
274static void
Jeremy Hylton06257772000-08-31 15:10:24 +0000275debug_instance(char *msg, PyInstanceObject *inst)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000276{
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000277 char *cname;
278 /* be careful not to create new dictionaries */
279 PyObject *classname = inst->in_class->cl_name;
280 if (classname != NULL && PyString_Check(classname))
281 cname = PyString_AsString(classname);
282 else
283 cname = "?";
Jeremy Hylton06257772000-08-31 15:10:24 +0000284 PySys_WriteStderr("gc: %.100s <%.100s instance at %p>\n",
285 msg, cname, inst);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000286}
287
288static void
Jeremy Hylton06257772000-08-31 15:10:24 +0000289debug_cycle(char *msg, PyObject *op)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000290{
291 if ((debug & DEBUG_INSTANCES) && PyInstance_Check(op)) {
Jeremy Hylton06257772000-08-31 15:10:24 +0000292 debug_instance(msg, (PyInstanceObject *)op);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000293 } else if (debug & DEBUG_OBJECTS) {
Jeremy Hylton06257772000-08-31 15:10:24 +0000294 PySys_WriteStderr("gc: %.100s <%.100s %p>\n",
295 msg, op->ob_type->tp_name, op);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000296 }
297}
298
299/* Handle uncollectable garbage (cycles with finalizers). */
300static void
301handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
302{
303 PyGC_Head *gc;
304 if (garbage == NULL) {
305 garbage = PyList_New(0);
306 }
307 for (gc = finalizers->gc_next; gc != finalizers;
308 gc = finalizers->gc_next) {
309 PyObject *op = PyObject_FROM_GC(gc);
310 /* Add all instances to a Python accessible list of garbage */
311 if (PyInstance_Check(op)) {
312 PyList_Append(garbage, op);
313 }
314 /* We assume that all objects in finalizers are reachable from
315 * instances. Once we add the instances to the garbage list
316 * everything is reachable from Python again. */
317 gc_list_remove(gc);
318 gc_list_append(gc, old);
319 }
320}
321
322/* Break reference cycles by clearing the containers involved. This is
323 * tricky business as the lists can be changing and we don't know which
324 * objects may be freed. It is possible I screwed something up here. */
325static void
326delete_garbage(PyGC_Head *unreachable, PyGC_Head *old)
327{
328 inquiry clear;
329
330 while (unreachable->gc_next != unreachable) {
331 PyGC_Head *gc = unreachable->gc_next;
332 PyObject *op = PyObject_FROM_GC(gc);
333 /*
334 PyList_Append(garbage, op);
335 */
336 if ((clear = op->ob_type->tp_clear) != NULL) {
337 Py_INCREF(op);
338 clear((PyObject *)op);
339 Py_DECREF(op);
340 }
341 /* only try to call tp_clear once for each object */
342 if (unreachable->gc_next == gc) {
343 /* still alive, move it, it may die later */
344 gc_list_remove(gc);
345 gc_list_append(gc, old);
346 }
347 }
348}
349
350/* This is the main function. Read this to understand how the
351 * collection process works. */
352static long
353collect(PyGC_Head *young, PyGC_Head *old)
354{
355 long n = 0;
356 long m = 0;
357 PyGC_Head reachable;
358 PyGC_Head unreachable;
359 PyGC_Head finalizers;
360 PyGC_Head *gc;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000361
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000362 if (debug & DEBUG_STATS) {
Jeremy Hylton06257772000-08-31 15:10:24 +0000363 PySys_WriteStderr(
364 "gc: collecting generation %d...\n"
365 "gc: objects in each generation: %ld %ld %ld\n",
366 generation,
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000367 gc_list_size(&generation0),
368 gc_list_size(&generation1),
369 gc_list_size(&generation2));
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000370 }
371
372 /* Using ob_refcnt and gc_refs, calculate which objects in the
373 * container set are reachable from outside the set (ie. have a
374 * refcount greater than 0 when all the references within the
375 * set are taken into account */
376 update_refs(young);
377 subtract_refs(young);
378
379 /* Move everything reachable from outside the set into the
380 * reachable set (ie. gc_refs > 0). Next, move everything
381 * reachable from objects in the reachable set. */
382 gc_list_init(&reachable);
383 move_roots(young, &reachable);
384 move_root_reachable(&reachable);
385
386 /* move unreachable objects to a temporary list, new objects can be
387 * allocated after this point */
388 gc_list_init(&unreachable);
389 gc_list_move(young, &unreachable);
390
391 /* move reachable objects to next generation */
392 gc_list_merge(&reachable, old);
393
394 /* Move objects reachable from finalizers, we can't safely delete
395 * them. Python programmers should take care not to create such
396 * things. For Python finalizers means instance objects with
397 * __del__ methods. */
398 gc_list_init(&finalizers);
399 move_finalizers(&unreachable, &finalizers);
400 move_finalizer_reachable(&finalizers);
401
402 /* Collect statistics on collectable objects found and print
403 * debugging information. */
404 for (gc = unreachable.gc_next; gc != &unreachable;
405 gc = gc->gc_next) {
406 m++;
Jeremy Hylton06257772000-08-31 15:10:24 +0000407 if (debug & DEBUG_COLLECTABLE) {
408 debug_cycle("collectable", PyObject_FROM_GC(gc));
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000409 }
410 }
411 /* call tp_clear on objects in the collectable set. This will cause
412 * the reference cycles to be broken. It may also cause some objects in
413 * finalizers to be freed */
414 delete_garbage(&unreachable, old);
415
416 /* Collect statistics on uncollectable objects found and print
417 * debugging information. */
418 for (gc = finalizers.gc_next; gc != &finalizers;
419 gc = gc->gc_next) {
420 n++;
Jeremy Hylton06257772000-08-31 15:10:24 +0000421 if (debug & DEBUG_UNCOLLECTABLE) {
422 debug_cycle("uncollectable", PyObject_FROM_GC(gc));
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000423 }
424 }
Jeremy Hylton06257772000-08-31 15:10:24 +0000425 if (debug & DEBUG_STATS) {
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000426 if (m == 0 && n == 0) {
Jeremy Hylton06257772000-08-31 15:10:24 +0000427 PySys_WriteStderr("gc: done.\n");
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000428 } else {
Jeremy Hylton06257772000-08-31 15:10:24 +0000429 PySys_WriteStderr(
430 "gc: done, %ld unreachable, %ld uncollectable.\n",
431 n+m, n);
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000432 }
433 }
434
435 /* Append instances in the uncollectable set to a Python
436 * reachable list of garbage. The programmer has to deal with
437 * this if they insist on creating this type of structure. */
438 handle_finalizers(&finalizers, old);
439
Jeremy Hyltonb709df32000-09-01 02:47:25 +0000440 if (PyErr_Occurred()) {
441 PyErr_WriteUnraisable(gc_str);
442 Py_FatalError("unexpected exception during garbage collection");
443 }
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000444 allocated = 0;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000445 return n+m;
446}
447
448static long
449collect_generations(void)
450{
451 static long collections0 = 0;
452 static long collections1 = 0;
Vladimir Marangozovb16714b2000-07-10 05:37:39 +0000453 long n = 0;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000454
455
456 if (collections1 > threshold2) {
457 generation = 2;
458 gc_list_merge(&generation0, &generation2);
459 gc_list_merge(&generation1, &generation2);
460 if (generation2.gc_next != &generation2) {
461 n = collect(&generation2, &generation2);
462 }
463 collections1 = 0;
464 } else if (collections0 > threshold1) {
465 generation = 1;
466 collections1++;
467 gc_list_merge(&generation0, &generation1);
468 if (generation1.gc_next != &generation1) {
469 n = collect(&generation1, &generation2);
470 }
471 collections0 = 0;
472 } else {
473 generation = 0;
474 collections0++;
475 if (generation0.gc_next != &generation0) {
476 n = collect(&generation0, &generation1);
477 }
478 }
479 return n;
480}
481
482void
483_PyGC_Insert(PyObject *op)
484{
485 /* collection lock since collecting may cause allocations */
486 static int collecting = 0;
487
488#ifdef Py_DEBUG
489 if (!PyObject_IS_GC(op)) {
490 abort();
491 }
492#endif
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000493 if (allocated > threshold0 && enabled && threshold0 && !collecting) {
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000494 collecting++;
495 collect_generations();
496 collecting--;
497 }
498 allocated++;
499 gc_list_append(PyObject_AS_GC(op), &generation0);
500}
501
502void
503_PyGC_Remove(PyObject *op)
504{
505 PyGC_Head *g = PyObject_AS_GC(op);
506#ifdef Py_DEBUG
507 if (!PyObject_IS_GC(op)) {
508 abort();
509 }
510#endif
511 gc_list_remove(g);
512 if (allocated > 0) {
513 allocated--;
514 }
515}
516
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000517static char gc_enable__doc__[] =
518"enable() -> None\n"
519"\n"
520"Enable automatic garbage collection.\n"
521;
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000522
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000523static PyObject *
524gc_enable(PyObject *self, PyObject *args)
525{
526
527 if (!PyArg_ParseTuple(args, ":enable")) /* check no args */
528 return NULL;
529
530 enabled = 1;
531
532 Py_INCREF(Py_None);
533 return Py_None;
534}
535
536static char gc_disable__doc__[] =
537"disable() -> None\n"
538"\n"
539"Disable automatic garbage collection.\n"
540;
541
542static PyObject *
543gc_disable(PyObject *self, PyObject *args)
544{
545
546 if (!PyArg_ParseTuple(args, ":disable")) /* check no args */
547 return NULL;
548
549 enabled = 0;
550
551 Py_INCREF(Py_None);
552 return Py_None;
553}
554
555static char gc_isenabled__doc__[] =
556"isenabled() -> status\n"
557"\n"
558"Returns true if automatic garbage collection is enabled.\n"
559;
560
561static PyObject *
562gc_isenabled(PyObject *self, PyObject *args)
563{
564
565 if (!PyArg_ParseTuple(args, ":isenabled")) /* check no args */
566 return NULL;
567
568 return Py_BuildValue("i", enabled);
569}
570
571static char gc_collect__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000572"collect() -> n\n"
573"\n"
574"Run a full collection. The number of unreachable objects is returned.\n"
575;
576
577static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000578gc_collect(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000579{
580 long n;
581
Fred Drakecc1be242000-07-12 04:42:23 +0000582 if (!PyArg_ParseTuple(args, ":collect")) /* check no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000583 return NULL;
584
585 generation = 2;
586 gc_list_merge(&generation0, &generation2);
587 gc_list_merge(&generation1, &generation2);
588 n = collect(&generation2, &generation2);
589
590 return Py_BuildValue("i", n);
591}
592
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000593static char gc_set_debug__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000594"set_debug(flags) -> None\n"
595"\n"
596"Set the garbage collection debugging flags. Debugging information is\n"
597"written to sys.stderr.\n"
598"\n"
599"flags is an integer and can have the following bits turned on:\n"
600"\n"
601" DEBUG_STATS - Print statistics during collection.\n"
602" DEBUG_COLLECTABLE - Print collectable objects found.\n"
603" DEBUG_UNCOLLECTABLE - Print unreachable but uncollectable objects found.\n"
604" DEBUG_INSTANCES - Print instance objects.\n"
605" DEBUG_OBJECTS - Print objects other than instances.\n"
606" DEBUG_LEAK - Debug leaking programs (everything but STATS).\n"
607;
608
609static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000610gc_set_debug(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000611{
Fred Drakecc1be242000-07-12 04:42:23 +0000612 if (!PyArg_ParseTuple(args, "l:get_debug", &debug))
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000613 return NULL;
614
615 Py_INCREF(Py_None);
616 return Py_None;
617}
618
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000619static char gc_get_debug__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000620"get_debug() -> flags\n"
621"\n"
622"Get the garbage collection debugging flags.\n"
623;
624
625static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000626gc_get_debug(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000627{
Fred Drakecc1be242000-07-12 04:42:23 +0000628 if (!PyArg_ParseTuple(args, ":get_debug")) /* no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000629 return NULL;
630
631 return Py_BuildValue("i", debug);
632}
633
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000634static char gc_set_thresh__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000635"set_threshold(threshold0, [threhold1, threshold2]) -> None\n"
636"\n"
637"Sets the collection thresholds. Setting threshold0 to zero disables\n"
638"collection.\n"
639;
640
641static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000642gc_set_thresh(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000643{
Fred Drakecc1be242000-07-12 04:42:23 +0000644 if (!PyArg_ParseTuple(args, "i|ii:set_threshold", &threshold0,
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000645 &threshold1, &threshold2))
646 return NULL;
647
648 Py_INCREF(Py_None);
649 return Py_None;
650}
651
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000652static char gc_get_thresh__doc__[] =
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000653"get_threshold() -> (threshold0, threshold1, threshold2)\n"
654"\n"
655"Return the current collection thresholds\n"
656;
657
658static PyObject *
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000659gc_get_thresh(PyObject *self, PyObject *args)
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000660{
Fred Drakecc1be242000-07-12 04:42:23 +0000661 if (!PyArg_ParseTuple(args, ":get_threshold")) /* no args */
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000662 return NULL;
663
664 return Py_BuildValue("(iii)", threshold0, threshold1, threshold2);
665}
666
667
668static char gc__doc__ [] =
669"This module provides access to the garbage collector for reference cycles.\n"
670"\n"
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000671"enable() -- Enable automatic garbage collection.\n"
672"disable() -- Disable automatic garbage collection.\n"
673"isenabled() -- Returns true if automatic collection is enabled.\n"
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000674"collect() -- Do a full collection right now.\n"
675"set_debug() -- Set debugging flags.\n"
676"get_debug() -- Get debugging flags.\n"
677"set_threshold() -- Set the collection thresholds.\n"
678"get_threshold() -- Return the current the collection thresholds.\n"
679;
680
681static PyMethodDef GcMethods[] = {
Vladimir Marangozovf9d20c32000-08-06 22:45:31 +0000682 {"enable", gc_enable, METH_VARARGS, gc_enable__doc__},
683 {"disable", gc_disable, METH_VARARGS, gc_disable__doc__},
684 {"isenabled", gc_isenabled, METH_VARARGS, gc_isenabled__doc__},
685 {"set_debug", gc_set_debug, METH_VARARGS, gc_set_debug__doc__},
686 {"get_debug", gc_get_debug, METH_VARARGS, gc_get_debug__doc__},
687 {"set_threshold", gc_set_thresh, METH_VARARGS, gc_set_thresh__doc__},
688 {"get_threshold", gc_get_thresh, METH_VARARGS, gc_get_thresh__doc__},
689 {"collect", gc_collect, METH_VARARGS, gc_collect__doc__},
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000690 {NULL, NULL} /* Sentinel */
691};
692
693void
694initgc(void)
695{
696 PyObject *m;
697 PyObject *d;
698
699 m = Py_InitModule4("gc",
700 GcMethods,
701 gc__doc__,
702 NULL,
703 PYTHON_API_VERSION);
704 d = PyModule_GetDict(m);
705 if (garbage == NULL) {
706 garbage = PyList_New(0);
707 }
Jeremy Hyltonb709df32000-09-01 02:47:25 +0000708 if (gc_str == NULL) {
709 gc_str = PyString_FromString("garbage collection");
710 }
Jeremy Hyltonc5007aa2000-06-30 05:02:53 +0000711 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 */