blob: 46e00638be90e3ab3d90fc5236079f0d95300673 [file] [log] [blame]
Fred Drake41deb1e2001-02-01 05:27:45 +00001#include "Python.h"
Fred Drake41deb1e2001-02-01 05:27:45 +00002
3
4#define GET_WEAKREFS_LISTPTR(o) \
5 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
6
Fred Drake41deb1e2001-02-01 05:27:45 +00007
Antoine Pitrouf939b3c2016-12-27 15:08:27 +01008static int
9is_dead_weakref(PyObject *value)
10{
11 if (!PyWeakref_Check(value)) {
12 PyErr_SetString(PyExc_TypeError, "not a weakref");
13 return -1;
14 }
15 return PyWeakref_GET_OBJECT(value) == Py_None;
16}
17
18PyDoc_STRVAR(remove_dead_weakref__doc__,
19"_remove_dead_weakref(dict, key) -- atomically remove key from dict\n"
20"if it points to a dead weakref.");
21
22static PyObject *
23remove_dead_weakref(PyObject *self, PyObject *args)
24{
25 PyObject *dct, *key;
26
27 if (!PyArg_ParseTuple(args, "O!O:_remove_dead_weakref",
28 &PyDict_Type, &dct, &key)) {
29 return NULL;
30 }
31 if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) {
32 if (PyErr_ExceptionMatches(PyExc_KeyError))
33 /* This function is meant to allow safe weak-value dicts
34 with GC in another thread (see issue #28427), so it's
35 ok if the key doesn't exist anymore.
36 */
37 PyErr_Clear();
38 else
39 return NULL;
40 }
41 Py_RETURN_NONE;
42}
43
44
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000045PyDoc_STRVAR(weakref_getweakrefcount__doc__,
Fred Drake7855aba2001-02-18 05:20:18 +000046"getweakrefcount(object) -- return the number of weak references\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000047"to 'object'.");
Fred Drake7855aba2001-02-18 05:20:18 +000048
Fred Drake41deb1e2001-02-01 05:27:45 +000049static PyObject *
Fred Drake7fdc0a12001-08-16 14:11:30 +000050weakref_getweakrefcount(PyObject *self, PyObject *object)
Fred Drake41deb1e2001-02-01 05:27:45 +000051{
52 PyObject *result = NULL;
Fred Drake41deb1e2001-02-01 05:27:45 +000053
Christian Heimese93237d2007-12-19 02:37:44 +000054 if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
Fred Drake7fdc0a12001-08-16 14:11:30 +000055 PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
Fred Drake41deb1e2001-02-01 05:27:45 +000056
Neal Norwitzc5e060d2006-08-02 06:14:22 +000057 result = PyInt_FromSsize_t(_PyWeakref_GetWeakrefCount(*list));
Fred Drake41deb1e2001-02-01 05:27:45 +000058 }
Fred Drake7fdc0a12001-08-16 14:11:30 +000059 else
60 result = PyInt_FromLong(0);
61
Fred Drake41deb1e2001-02-01 05:27:45 +000062 return result;
63}
64
65
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000066PyDoc_STRVAR(weakref_getweakrefs__doc__,
Fred Drake7855aba2001-02-18 05:20:18 +000067"getweakrefs(object) -- return a list of all weak reference objects\n"
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000068"that point to 'object'.");
Fred Drake7855aba2001-02-18 05:20:18 +000069
Fred Drake41deb1e2001-02-01 05:27:45 +000070static PyObject *
Fred Drake7fdc0a12001-08-16 14:11:30 +000071weakref_getweakrefs(PyObject *self, PyObject *object)
Fred Drake41deb1e2001-02-01 05:27:45 +000072{
73 PyObject *result = NULL;
Fred Drake41deb1e2001-02-01 05:27:45 +000074
Christian Heimese93237d2007-12-19 02:37:44 +000075 if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
Fred Drake7fdc0a12001-08-16 14:11:30 +000076 PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
Neal Norwitzc5e060d2006-08-02 06:14:22 +000077 Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
Fred Drake41deb1e2001-02-01 05:27:45 +000078
Fred Drake7fdc0a12001-08-16 14:11:30 +000079 result = PyList_New(count);
80 if (result != NULL) {
81 PyWeakReference *current = *list;
Neal Norwitzc5e060d2006-08-02 06:14:22 +000082 Py_ssize_t i;
Fred Drake7fdc0a12001-08-16 14:11:30 +000083 for (i = 0; i < count; ++i) {
84 PyList_SET_ITEM(result, i, (PyObject *) current);
85 Py_INCREF(current);
86 current = current->wr_next;
Fred Drake41deb1e2001-02-01 05:27:45 +000087 }
88 }
Fred Drake7fdc0a12001-08-16 14:11:30 +000089 }
90 else {
91 result = PyList_New(0);
Fred Drake41deb1e2001-02-01 05:27:45 +000092 }
93 return result;
94}
95
96
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000097PyDoc_STRVAR(weakref_proxy__doc__,
Fred Drake7855aba2001-02-18 05:20:18 +000098"proxy(object[, callback]) -- create a proxy object that weakly\n"
99"references 'object'. 'callback', if given, is called with a\n"
Fred Drake610291c2002-08-02 20:23:40 +0000100"reference to the proxy when 'object' is about to be finalized.");
Fred Drake7855aba2001-02-18 05:20:18 +0000101
Fred Drake41deb1e2001-02-01 05:27:45 +0000102static PyObject *
103weakref_proxy(PyObject *self, PyObject *args)
104{
105 PyObject *object;
106 PyObject *callback = NULL;
Fred Drakef7f8cad2001-10-05 22:00:24 +0000107 PyObject *result = NULL;
Fred Drake41deb1e2001-02-01 05:27:45 +0000108
Fred Drake0d429e82001-10-23 21:12:47 +0000109 if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) {
Fred Drakef7f8cad2001-10-05 22:00:24 +0000110 result = PyWeakref_NewProxy(object, callback);
Fred Drake41deb1e2001-02-01 05:27:45 +0000111 }
Fred Drakef7f8cad2001-10-05 22:00:24 +0000112 return result;
Fred Drake41deb1e2001-02-01 05:27:45 +0000113}
114
115
116static PyMethodDef
117weakref_functions[] = {
Fred Drake7fdc0a12001-08-16 14:11:30 +0000118 {"getweakrefcount", weakref_getweakrefcount, METH_O,
Fred Drake7855aba2001-02-18 05:20:18 +0000119 weakref_getweakrefcount__doc__},
Fred Drake7fdc0a12001-08-16 14:11:30 +0000120 {"getweakrefs", weakref_getweakrefs, METH_O,
Fred Drake7855aba2001-02-18 05:20:18 +0000121 weakref_getweakrefs__doc__},
122 {"proxy", weakref_proxy, METH_VARARGS,
123 weakref_proxy__doc__},
Antoine Pitrouf939b3c2016-12-27 15:08:27 +0100124 {"_remove_dead_weakref", remove_dead_weakref, METH_VARARGS,
125 remove_dead_weakref__doc__},
Fred Drake41deb1e2001-02-01 05:27:45 +0000126 {NULL, NULL, 0, NULL}
127};
128
129
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000130PyMODINIT_FUNC
Fred Drake41deb1e2001-02-01 05:27:45 +0000131init_weakref(void)
132{
133 PyObject *m;
134
Fred Drake41deb1e2001-02-01 05:27:45 +0000135 m = Py_InitModule3("_weakref", weakref_functions,
136 "Weak-reference support module.");
137 if (m != NULL) {
Fred Drakef7f8cad2001-10-05 22:00:24 +0000138 Py_INCREF(&_PyWeakref_RefType);
Fred Drake0a4dd392004-07-02 18:57:45 +0000139 PyModule_AddObject(m, "ref",
140 (PyObject *) &_PyWeakref_RefType);
141 Py_INCREF(&_PyWeakref_RefType);
Fred Drake41deb1e2001-02-01 05:27:45 +0000142 PyModule_AddObject(m, "ReferenceType",
Fred Drakef7f8cad2001-10-05 22:00:24 +0000143 (PyObject *) &_PyWeakref_RefType);
144 Py_INCREF(&_PyWeakref_ProxyType);
Fred Drake41deb1e2001-02-01 05:27:45 +0000145 PyModule_AddObject(m, "ProxyType",
Fred Drakef7f8cad2001-10-05 22:00:24 +0000146 (PyObject *) &_PyWeakref_ProxyType);
147 Py_INCREF(&_PyWeakref_CallableProxyType);
Fred Drake41deb1e2001-02-01 05:27:45 +0000148 PyModule_AddObject(m, "CallableProxyType",
Fred Drakef7f8cad2001-10-05 22:00:24 +0000149 (PyObject *) &_PyWeakref_CallableProxyType);
Fred Drake41deb1e2001-02-01 05:27:45 +0000150 }
151}