blob: 3c03c3c19ba8b9efe1242dcbd12661f06531a3c6 [file] [log] [blame]
Fred Drake41deb1e2001-02-01 05:27:45 +00001#include "Python.h"
2#include "structmember.h"
3
4
5typedef struct _PyWeakReference PyWeakReference;
6
7struct _PyWeakReference {
8 PyObject_HEAD
9 PyObject *wr_object;
10 PyObject *wr_callback;
11 PyWeakReference *wr_prev;
12 PyWeakReference *wr_next;
13};
14
15
16#define GET_WEAKREFS_LISTPTR(o) \
17 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
18
19static PyObject *
20ReferenceError;
21
22static PyWeakReference *
23free_list = NULL;
24
25staticforward PyTypeObject
26PyWeakReference_Type;
27
28static PyWeakReference *
29new_weakref(void)
30{
31 PyWeakReference *result;
32
33 if (free_list != NULL) {
34 result = free_list;
35 free_list = result->wr_next;
36 result->ob_type = &PyWeakReference_Type;
37 _Py_NewReference(result);
38 }
39 else {
40 result = PyObject_NEW(PyWeakReference, &PyWeakReference_Type);
41 }
42 return result;
43}
44
45
46/* This function clears the passed-in reference and removes it from the
47 * list of weak references for the referent. This is the only code that
48 * removes an item from the doubly-linked list of weak references for an
49 * object; it is also responsible for clearing the callback slot.
50 */
51static void
52clear_weakref(PyWeakReference *self)
53{
54 PyObject *callback = self->wr_callback;
55
56 if (self->wr_object != Py_None) {
57 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
58
59 if (*list == self)
60 *list = self->wr_next;
61 self->wr_object = Py_None;
62 self->wr_callback = NULL;
63 if (self->wr_prev != NULL)
64 self->wr_prev->wr_next = self->wr_next;
65 if (self->wr_next != NULL)
66 self->wr_next->wr_prev = self->wr_prev;
67 self->wr_prev = NULL;
68 self->wr_next = NULL;
69 Py_XDECREF(callback);
70 }
71}
72
73
74static void
75weakref_dealloc(PyWeakReference *self)
76{
77 clear_weakref(self);
78 PyObject_GC_Fini((PyObject *)self);
79 self->wr_next = free_list;
80 free_list = self;
81}
82
83
84static int
85gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
86{
87 if (self->wr_callback != NULL)
88 return visit(self->wr_callback, arg);
89 return 0;
90}
91
92
93static int
94gc_clear(PyWeakReference *self)
95{
96 clear_weakref(self);
97 return 0;
98}
99
100
101static PyObject *
102weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
103{
104 static char *argnames[] = {NULL};
105
106 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", argnames)) {
107 PyObject *object = self->wr_object;
108 Py_INCREF(object);
109 return (object);
110 }
111 return NULL;
112}
113
114
115static PyObject *
116weakref_repr(PyWeakReference *self)
117{
118 char buffer[256];
119 if (self->wr_object == Py_None) {
120 sprintf(buffer, "<weakref at %lx; dead>",
121 (long)(self));
122 }
123 else {
124 sprintf(buffer, "<weakref at %#lx; to '%s' at %#lx>",
125 (long)(self), self->wr_object->ob_type->tp_name,
126 (long)(self->wr_object));
127 }
128 return PyString_FromString(buffer);
129}
130
131
132statichere PyTypeObject
133PyWeakReference_Type = {
134 PyObject_HEAD_INIT(NULL)
135 0,
136 "weakref",
137 sizeof(PyWeakReference) + PyGC_HEAD_SIZE,
138 0,
139 (destructor)weakref_dealloc,/*tp_dealloc*/
140 0, /*tp_print*/
141 0, /*tp_getattr*/
142 0, /*tp_setattr*/
143 0, /*tp_compare*/
144 (reprfunc)weakref_repr, /*tp_repr*/
145 0, /*tp_as_number*/
146 0, /*tp_as_sequence*/
147 0, /*tp_as_mapping*/
148 0, /*tp_hash*/
149 (ternaryfunc)weakref_call, /*tp_call*/
150 0, /*tp_str*/
151 0, /*tp_getattro*/
152 0, /*tp_setattro*/
153 0, /*tp_as_buffer*/
154 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC,
155 0, /*tp_doc*/
156 (traverseproc)gc_traverse, /*tp_traverse*/
157 (inquiry)gc_clear, /*tp_clear*/
158};
159
160
161static int
162proxy_checkref(PyWeakReference *proxy)
163{
164 if (proxy->wr_object == Py_None) {
165 PyErr_SetString(ReferenceError,
166 "weakly-referenced object no longer exists");
167 return 0;
168 }
169 return 1;
170}
171
172
173#define WRAP_UNARY(method, generic) \
174 static PyObject * \
175 method(PyWeakReference *proxy) { \
176 if (!proxy_checkref(proxy)) { \
177 return NULL; \
178 } \
179 return generic(proxy->wr_object); \
180 }
181
182#define WRAP_BINARY(method, generic) \
183 static PyObject * \
184 method(PyWeakReference *proxy, PyObject *v) { \
185 if (!proxy_checkref(proxy)) { \
186 return NULL; \
187 } \
188 return generic(proxy->wr_object, v); \
189 }
190
191#define WRAP_TERNARY(method, generic) \
192 static PyObject * \
193 method(PyWeakReference *proxy, PyObject *v, PyObject *w) { \
194 if (!proxy_checkref(proxy)) { \
195 return NULL; \
196 } \
197 return generic(proxy->wr_object, v, w); \
198 }
199
200
201/* direct slots */
202
203WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
204WRAP_UNARY(proxy_str, PyObject_Str)
205WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
206
207static int
208proxy_print(PyWeakReference *proxy, FILE *fp, int flags)
209{
210 if (!proxy_checkref(proxy))
211 return -1;
212 return PyObject_Print(proxy->wr_object, fp, flags);
213}
214
215static PyObject *
216proxy_repr(PyWeakReference *proxy)
217{
218 char buf[160];
219 sprintf(buf, "<weakref at %p to %.100s at %p>", proxy,
220 proxy->wr_object->ob_type->tp_name, proxy->wr_object);
221 return PyString_FromString(buf);
222}
223
224
225static int
226proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
227{
228 if (!proxy_checkref(proxy))
229 return -1;
230 return PyObject_SetAttr(proxy->wr_object, name, value);
231}
232
233static int
234proxy_compare(PyWeakReference *proxy, PyObject *v)
235{
236 if (!proxy_checkref(proxy))
237 return -1;
238 return PyObject_Compare(proxy->wr_object, v);
239}
240
241/* number slots */
242WRAP_BINARY(proxy_add, PyNumber_Add)
243WRAP_BINARY(proxy_sub, PyNumber_Subtract)
244WRAP_BINARY(proxy_mul, PyNumber_Multiply)
245WRAP_BINARY(proxy_div, PyNumber_Divide)
246WRAP_BINARY(proxy_mod, PyNumber_Remainder)
247WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
248WRAP_TERNARY(proxy_pow, PyNumber_Power)
249WRAP_UNARY(proxy_neg, PyNumber_Negative)
250WRAP_UNARY(proxy_pos, PyNumber_Positive)
251WRAP_UNARY(proxy_abs, PyNumber_Absolute)
252WRAP_UNARY(proxy_invert, PyNumber_Invert)
253WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
254WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
255WRAP_BINARY(proxy_and, PyNumber_And)
256WRAP_BINARY(proxy_xor, PyNumber_Xor)
257WRAP_BINARY(proxy_or, PyNumber_Or)
258WRAP_UNARY(proxy_int, PyNumber_Int)
259WRAP_UNARY(proxy_long, PyNumber_Long)
260WRAP_UNARY(proxy_float, PyNumber_Float)
261WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
262WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
263WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
264WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
265WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
266WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
267WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
268WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
269WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
270WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
271WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
272
273static int
274proxy_nonzero(PyWeakReference *proxy)
275{
276 PyObject *o = proxy->wr_object;
277 if (!proxy_checkref(proxy))
278 return 1;
279 if (o->ob_type->tp_as_number &&
280 o->ob_type->tp_as_number->nb_nonzero)
281 return (*o->ob_type->tp_as_number->nb_nonzero)(o);
282 else
283 return 1;
284}
285
286/* sequence slots */
287
288static PyObject *
289proxy_slice(PyWeakReference *proxy, int i, int j)
290{
291 if (!proxy_checkref(proxy))
292 return NULL;
293 return PySequence_GetSlice(proxy->wr_object, i, j);
294}
295
296static int
297proxy_ass_slice(PyWeakReference *proxy, int i, int j, PyObject *value)
298{
299 if (!proxy_checkref(proxy))
300 return -1;
301 return PySequence_SetSlice(proxy->wr_object, i, j, value);
302}
303
304static int
305proxy_contains(PyWeakReference *proxy, PyObject *value)
306{
307 if (!proxy_checkref(proxy))
308 return -1;
309 return PySequence_Contains(proxy->wr_object, value);
310}
311
312
313/* mapping slots */
314
315static int
316proxy_length(PyWeakReference *proxy)
317{
318 if (!proxy_checkref(proxy))
319 return -1;
320 return PyObject_Length(proxy->wr_object);
321}
322
323WRAP_BINARY(proxy_getitem, PyObject_GetItem)
324
325static int
326proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
327{
328 if (!proxy_checkref(proxy))
329 return -1;
330 return PyObject_SetItem(proxy->wr_object, key, value);
331}
332
333
334static PyNumberMethods proxy_as_number = {
335 (binaryfunc)proxy_add, /*nb_add*/
336 (binaryfunc)proxy_sub, /*nb_subtract*/
337 (binaryfunc)proxy_mul, /*nb_multiply*/
338 (binaryfunc)proxy_div, /*nb_divide*/
339 (binaryfunc)proxy_mod, /*nb_remainder*/
340 (binaryfunc)proxy_divmod, /*nb_divmod*/
341 (ternaryfunc)proxy_pow, /*nb_power*/
342 (unaryfunc)proxy_neg, /*nb_negative*/
343 (unaryfunc)proxy_pos, /*nb_positive*/
344 (unaryfunc)proxy_abs, /*nb_absolute*/
345 (inquiry)proxy_nonzero, /*nb_nonzero*/
346 (unaryfunc)proxy_invert, /*nb_invert*/
347 (binaryfunc)proxy_lshift, /*nb_lshift*/
348 (binaryfunc)proxy_rshift, /*nb_rshift*/
349 (binaryfunc)proxy_and, /*nb_and*/
350 (binaryfunc)proxy_xor, /*nb_xor*/
351 (binaryfunc)proxy_or, /*nb_or*/
352 (coercion)0, /*nb_coerce*/
353 (unaryfunc)proxy_int, /*nb_int*/
354 (unaryfunc)proxy_long, /*nb_long*/
355 (unaryfunc)proxy_float, /*nb_float*/
356 (unaryfunc)0, /*nb_oct*/
357 (unaryfunc)0, /*nb_hex*/
358 (binaryfunc)proxy_iadd, /*nb_inplace_add*/
359 (binaryfunc)proxy_isub, /*nb_inplace_subtract*/
360 (binaryfunc)proxy_imul, /*nb_inplace_multiply*/
361 (binaryfunc)proxy_idiv, /*nb_inplace_divide*/
362 (binaryfunc)proxy_imod, /*nb_inplace_remainder*/
363 (ternaryfunc)proxy_ipow, /*nb_inplace_power*/
364 (binaryfunc)proxy_ilshift, /*nb_inplace_lshift*/
365 (binaryfunc)proxy_irshift, /*nb_inplace_rshift*/
366 (binaryfunc)proxy_iand, /*nb_inplace_and*/
367 (binaryfunc)proxy_ixor, /*nb_inplace_xor*/
368 (binaryfunc)proxy_ior, /*nb_inplace_or*/
369};
370
371static PySequenceMethods proxy_as_sequence = {
372 (inquiry)proxy_length, /*sq_length*/
373 0, /*sq_concat*/
374 0, /*sq_repeat*/
375 0, /*sq_item*/
376 (intintargfunc)proxy_slice, /*sq_slice*/
377 0, /*sq_ass_item*/
378 (intintobjargproc)proxy_ass_slice, /*sq_ass_slice*/
379 (objobjproc)proxy_contains, /* sq_contains */
380};
381
382static PyMappingMethods proxy_as_mapping = {
383 (inquiry)proxy_length, /*mp_length*/
384 (binaryfunc)proxy_getitem, /*mp_subscript*/
385 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
386};
387
388
389static PyTypeObject
390PyWeakProxy_Type = {
391 PyObject_HEAD_INIT(NULL)
392 0,
393 "weakproxy",
394 sizeof(PyWeakReference) + PyGC_HEAD_SIZE,
395 0,
396 /* methods */
397 (destructor)weakref_dealloc,/*tp_dealloc*/
398 (printfunc)proxy_print, /*tp_print*/
399 0, /*tp_getattr*/
400 0, /*tp_setattr*/
401 (cmpfunc)proxy_compare, /*tp_compare*/
402 (unaryfunc)proxy_repr, /*tp_repr*/
403 &proxy_as_number, /*tp_as_number*/
404 &proxy_as_sequence, /*tp_as_sequence*/
405 &proxy_as_mapping, /*tp_as_mapping*/
406 0, /*tp_hash*/
407 (ternaryfunc)0, /*tp_call*/
408 (unaryfunc)proxy_str, /*tp_str*/
409 (getattrofunc)proxy_getattr,/*tp_getattro*/
410 (setattrofunc)proxy_setattr,/*tp_setattro*/
411 0, /*tp_as_buffer*/
412 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC
413 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
414 0, /*tp_doc*/
415 (traverseproc)gc_traverse, /*tp_traverse*/
416 (inquiry)gc_clear, /*tp_clear*/
417};
418
419
420static PyTypeObject
421PyWeakCallableProxy_Type = {
422 PyObject_HEAD_INIT(NULL)
423 0,
424 "weakcallableproxy",
425 sizeof(PyWeakReference) + PyGC_HEAD_SIZE,
426 0,
427 /* methods */
428 (destructor)weakref_dealloc,/*tp_dealloc*/
429 (printfunc)proxy_print, /*tp_print*/
430 0, /*tp_getattr*/
431 0, /*tp_setattr*/
432 (cmpfunc)proxy_compare, /*tp_compare*/
433 (unaryfunc)proxy_repr, /*tp_repr*/
434 &proxy_as_number, /*tp_as_number*/
435 &proxy_as_sequence, /*tp_as_sequence*/
436 &proxy_as_mapping, /*tp_as_mapping*/
437 0, /*tp_hash*/
438 (ternaryfunc)proxy_call, /*tp_call*/
439 (unaryfunc)proxy_str, /*tp_str*/
440 (getattrofunc)proxy_getattr,/*tp_getattro*/
441 (setattrofunc)proxy_setattr,/*tp_setattro*/
442 0, /*tp_as_buffer*/
443 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC
444 |Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
445 0, /*tp_doc*/
446 (traverseproc)gc_traverse, /*tp_traverse*/
447 (inquiry)gc_clear, /*tp_clear*/
448};
449
450
451static long
452getweakrefcount(PyWeakReference *head)
453{
454 long count = 0;
455
456 while (head != NULL) {
457 ++count;
458 head = head->wr_next;
459 }
460 return count;
461}
462
463
464static PyObject *
465weakref_getweakrefcount(PyObject *self, PyObject *args)
466{
467 PyObject *result = NULL;
468 PyObject *object;
469
470 if (PyArg_ParseTuple(args, "O:getweakrefcount", &object)) {
471 if (PyType_SUPPORTS_WEAKREFS(object->ob_type)) {
472 PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
473
474 result = PyInt_FromLong(getweakrefcount(*list));
475 }
476 else
477 result = PyInt_FromLong(0);
478 }
479 return result;
480}
481
482
483static PyObject *
484weakref_getweakrefs(PyObject *self, PyObject *args)
485{
486 PyObject *result = NULL;
487 PyObject *object;
488
489 if (PyArg_ParseTuple(args, "O:getweakrefs", &object)) {
490 if (PyType_SUPPORTS_WEAKREFS(object->ob_type)) {
491 PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
492 long count = getweakrefcount(*list);
493
494 result = PyList_New(count);
495 if (result != NULL) {
496 PyWeakReference *current = *list;
497 long i;
498 for (i = 0; i < count; ++i) {
499 PyList_SET_ITEM(result, i, (PyObject *) current);
500 Py_INCREF(current);
501 current = current->wr_next;
502 }
503 }
504 }
505 else {
506 result = PyList_New(0);
507 }
508 }
509 return result;
510}
511
512
513/* Given the head of an object's list of weak references, extract the
514 * two callback-less refs (ref and proxy). Used to determine if the
515 * shared references exist and to determine the back link for newly
516 * inserted references.
517 */
518static void
519get_basic_refs(PyWeakReference *head,
520 PyWeakReference **refp, PyWeakReference **proxyp)
521{
522 *refp = NULL;
523 *proxyp = NULL;
524
525 if (head != NULL && head->wr_callback == NULL) {
526 if (head->ob_type == &PyWeakReference_Type) {
527 *refp = head;
528 head = head->wr_next;
529 }
530 if (head != NULL && head->wr_callback == NULL) {
531 *proxyp = head;
532 head = head->wr_next;
533 }
534 }
535}
536
537/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
538static void
539insert_after(PyWeakReference *newref, PyWeakReference *prev)
540{
541 newref->wr_prev = prev;
542 newref->wr_next = prev->wr_next;
543 if (prev->wr_next != NULL)
544 prev->wr_next->wr_prev = newref;
545 prev->wr_next = newref;
546}
547
548/* Insert 'newref' at the head of the list; 'list' points to the variable
549 * that stores the head.
550 */
551static void
552insert_head(PyWeakReference *newref, PyWeakReference **list)
553{
554 PyWeakReference *next = *list;
555
556 newref->wr_prev = NULL;
557 newref->wr_next = next;
558 if (next != NULL)
559 next->wr_prev = newref;
560 *list = newref;
561}
562
563
564static PyObject *
565weakref_ref(PyObject *self, PyObject *args)
566{
567 PyObject *object;
568 PyObject *callback = NULL;
569 PyWeakReference *result = NULL;
570
571 if (PyArg_ParseTuple(args, "O|O:new", &object, &callback)) {
572 PyWeakReference **list;
573 PyWeakReference *ref, *proxy;
574
575 if (!PyType_SUPPORTS_WEAKREFS(object->ob_type)) {
576 PyErr_Format(PyExc_TypeError,
577 "'%s' objects are not weakly referencable",
578 object->ob_type->tp_name);
579 return NULL;
580 }
581 list = GET_WEAKREFS_LISTPTR(object);
582 get_basic_refs(*list, &ref, &proxy);
583 if (callback == NULL) {
584 /* return existing weak reference if it exists */
585 result = ref;
586 Py_XINCREF(result);
587 }
588 if (result == NULL) {
589 result = new_weakref();
590 if (result != NULL) {
591 Py_XINCREF(callback);
592 result->wr_callback = callback;
593 result->wr_object = object;
594 if (callback == NULL) {
595 insert_head(result, list);
596 }
597 else {
598 PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
599
600 if (prev == NULL)
601 insert_head(result, list);
602 else
603 insert_after(result, prev);
604 }
605 PyObject_GC_Init((PyObject *) result);
606 }
607 }
608 }
609 return (PyObject *) result;
610}
611
612
613static PyObject *
614weakref_proxy(PyObject *self, PyObject *args)
615{
616 PyObject *object;
617 PyObject *callback = NULL;
618 PyWeakReference *result = NULL;
619
620 if (PyArg_ParseTuple(args, "O|O:new", &object, &callback)) {
621 PyWeakReference **list;
622 PyWeakReference *ref, *proxy;
623
624 if (!PyType_SUPPORTS_WEAKREFS(object->ob_type)) {
625 PyErr_Format(PyExc_TypeError,
626 "'%s' objects are not weakly referencable",
627 object->ob_type->tp_name);
628 return NULL;
629 }
630 list = GET_WEAKREFS_LISTPTR(object);
631 get_basic_refs(*list, &ref, &proxy);
632 if (callback == NULL) {
633 /* attempt to return an existing weak reference if it exists */
634 result = proxy;
635 Py_XINCREF(result);
636 }
637 if (result == NULL) {
638 result = new_weakref();
639 if (result != NULL) {
640 PyWeakReference *prev;
641
642 if (PyCallable_Check(object))
643 result->ob_type = &PyWeakCallableProxy_Type;
644 else
645 result->ob_type = &PyWeakProxy_Type;
646 result->wr_object = object;
647 Py_XINCREF(callback);
648 result->wr_callback = callback;
649 if (callback == NULL)
650 prev = ref;
651 else
652 prev = (proxy == NULL) ? ref : proxy;
653
654 if (prev == NULL)
655 insert_head(result, list);
656 else
657 insert_after(result, prev);
658 PyObject_GC_Init((PyObject *) result);
659 }
660 }
661 }
662 return (PyObject *) result;
663}
664
665
666/* This is the implementation of the PyObject_ClearWeakRefs() function; it
667 * is installed in the init_weakref() function. It is called by the
668 * tp_dealloc handler to clear weak references.
669 *
670 * This returns true if the object should be deallocated, and false if the
671 * object is resurrected and deallocation should be aborted.
672 *
673 * This iterates through the weak references for 'object' and calls callbacks
674 * until one resurrects the object, at which point it stops invalidating
675 * weak references and returns false.
676 */
677static int
678cleanup_helper(PyObject *object)
679{
680 PyWeakReference **list;
681
682 if (object == NULL
683 || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
684 || object->ob_refcnt != 0) {
685 PyErr_BadInternalCall();
686 /* not sure what we should return here */
687 return 1;
688 }
689 list = GET_WEAKREFS_LISTPTR(object);
690 while (*list != NULL) {
691 PyWeakReference *current = *list;
692 PyObject *callback = current->wr_callback;
693
694 Py_XINCREF(callback);
695 clear_weakref(current);
696 if (callback != NULL) {
697 PyObject *cbresult;
698
699 cbresult = PyObject_CallFunction(callback, "O", current);
700 if (cbresult == NULL)
701 PyErr_WriteUnraisable(callback);
702 else
703 Py_DECREF(cbresult);
704 Py_DECREF(callback);
705 }
706 }
707 return (object->ob_refcnt > 0 ? 0 : 1);
708}
709
710
711static PyMethodDef
712weakref_functions[] = {
713 {"getweakrefcount", weakref_getweakrefcount, METH_VARARGS,
714 "getweakrefcount(object) -- return the number of weak references\n"
715 "to 'object'."},
716 {"getweakrefs", weakref_getweakrefs, METH_VARARGS,
717 "getweakrefs(object) -- return a list of all weak reference objects\n"
718 "that point to 'object'."},
719 {"proxy", weakref_proxy, METH_VARARGS,
720 "proxy(object[, callback]) -- create a proxy object that weakly\n"
721 "references 'object'. 'callback', if given, is called with a\n"
722 "reference to 'object' when it is about to be finalized."},
723 {"ref", weakref_ref, METH_VARARGS,
724 "new(object[, callback]) -- create a weak reference to 'object';\n"
725 "when 'object' is finalized, 'callback' will be called and passed\n"
726 "a reference to 'object'."},
727 {NULL, NULL, 0, NULL}
728};
729
730
731void
732init_weakref(void)
733{
734 PyObject *m;
735
736 PyWeakReference_Type.ob_type = &PyType_Type;
737 PyWeakProxy_Type.ob_type = &PyType_Type;
738 PyWeakCallableProxy_Type.ob_type = &PyType_Type;
739 m = Py_InitModule3("_weakref", weakref_functions,
740 "Weak-reference support module.");
741 if (m != NULL) {
742 PyObject_ClearWeakRefs = cleanup_helper;
743 Py_INCREF(&PyWeakReference_Type);
744 PyModule_AddObject(m, "ReferenceType",
745 (PyObject *) &PyWeakReference_Type);
746 Py_INCREF(&PyWeakProxy_Type);
747 PyModule_AddObject(m, "ProxyType",
748 (PyObject *) &PyWeakProxy_Type);
749 Py_INCREF(&PyWeakCallableProxy_Type);
750 PyModule_AddObject(m, "CallableProxyType",
751 (PyObject *) &PyWeakCallableProxy_Type);
752 ReferenceError = PyErr_NewException("weakref.ReferenceError",
753 PyExc_RuntimeError, NULL);
754 if (ReferenceError != NULL)
755 PyModule_AddObject(m, "ReferenceError", ReferenceError);
756 }
757}