X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=AppPkg%2FApplications%2FPython%2FPython-2.7.2%2FObjects%2Fweakrefobject.c;fp=AppPkg%2FApplications%2FPython%2FPython-2.7.2%2FObjects%2Fweakrefobject.c;h=0000000000000000000000000000000000000000;hp=f852aea349dd6affda11b62257c8508574acd827;hb=964f432b9b0afe103c41c7613fade3e699118afe;hpb=e2d3a25f1a3135221a9c8061e1b8f90245d727eb diff --git a/AppPkg/Applications/Python/Python-2.7.2/Objects/weakrefobject.c b/AppPkg/Applications/Python/Python-2.7.2/Objects/weakrefobject.c deleted file mode 100644 index f852aea349..0000000000 --- a/AppPkg/Applications/Python/Python-2.7.2/Objects/weakrefobject.c +++ /dev/null @@ -1,975 +0,0 @@ -#include "Python.h" -#include "structmember.h" - - -#define GET_WEAKREFS_LISTPTR(o) \ - ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o)) - - -Py_ssize_t -_PyWeakref_GetWeakrefCount(PyWeakReference *head) -{ - Py_ssize_t count = 0; - - while (head != NULL) { - ++count; - head = head->wr_next; - } - return count; -} - - -static void -init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback) -{ - self->hash = -1; - self->wr_object = ob; - Py_XINCREF(callback); - self->wr_callback = callback; -} - -static PyWeakReference * -new_weakref(PyObject *ob, PyObject *callback) -{ - PyWeakReference *result; - - result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType); - if (result) { - init_weakref(result, ob, callback); - PyObject_GC_Track(result); - } - return result; -} - - -/* This function clears the passed-in reference and removes it from the - * list of weak references for the referent. This is the only code that - * removes an item from the doubly-linked list of weak references for an - * object; it is also responsible for clearing the callback slot. - */ -static void -clear_weakref(PyWeakReference *self) -{ - PyObject *callback = self->wr_callback; - - if (PyWeakref_GET_OBJECT(self) != Py_None) { - PyWeakReference **list = GET_WEAKREFS_LISTPTR( - PyWeakref_GET_OBJECT(self)); - - if (*list == self) - /* If 'self' is the end of the list (and thus self->wr_next == NULL) - then the weakref list itself (and thus the value of *list) will - end up being set to NULL. */ - *list = self->wr_next; - self->wr_object = Py_None; - if (self->wr_prev != NULL) - self->wr_prev->wr_next = self->wr_next; - if (self->wr_next != NULL) - self->wr_next->wr_prev = self->wr_prev; - self->wr_prev = NULL; - self->wr_next = NULL; - } - if (callback != NULL) { - Py_DECREF(callback); - self->wr_callback = NULL; - } -} - -/* Cyclic gc uses this to *just* clear the passed-in reference, leaving - * the callback intact and uncalled. It must be possible to call self's - * tp_dealloc() after calling this, so self has to be left in a sane enough - * state for that to work. We expect tp_dealloc to decref the callback - * then. The reason for not letting clear_weakref() decref the callback - * right now is that if the callback goes away, that may in turn trigger - * another callback (if a weak reference to the callback exists) -- running - * arbitrary Python code in the middle of gc is a disaster. The convolution - * here allows gc to delay triggering such callbacks until the world is in - * a sane state again. - */ -void -_PyWeakref_ClearRef(PyWeakReference *self) -{ - PyObject *callback; - - assert(self != NULL); - assert(PyWeakref_Check(self)); - /* Preserve and restore the callback around clear_weakref. */ - callback = self->wr_callback; - self->wr_callback = NULL; - clear_weakref(self); - self->wr_callback = callback; -} - -static void -weakref_dealloc(PyObject *self) -{ - PyObject_GC_UnTrack(self); - clear_weakref((PyWeakReference *) self); - Py_TYPE(self)->tp_free(self); -} - - -static int -gc_traverse(PyWeakReference *self, visitproc visit, void *arg) -{ - Py_VISIT(self->wr_callback); - return 0; -} - - -static int -gc_clear(PyWeakReference *self) -{ - clear_weakref(self); - return 0; -} - - -static PyObject * -weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw) -{ - static char *kwlist[] = {NULL}; - - if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) { - PyObject *object = PyWeakref_GET_OBJECT(self); - Py_INCREF(object); - return (object); - } - return NULL; -} - - -static long -weakref_hash(PyWeakReference *self) -{ - if (self->hash != -1) - return self->hash; - if (PyWeakref_GET_OBJECT(self) == Py_None) { - PyErr_SetString(PyExc_TypeError, "weak object has gone away"); - return -1; - } - self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self)); - return self->hash; -} - - -static PyObject * -weakref_repr(PyWeakReference *self) -{ - char buffer[256]; - if (PyWeakref_GET_OBJECT(self) == Py_None) { - PyOS_snprintf(buffer, sizeof(buffer), "", self); - } - else { - char *name = NULL; - PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self), - "__name__"); - if (nameobj == NULL) - PyErr_Clear(); - else if (PyString_Check(nameobj)) - name = PyString_AS_STRING(nameobj); - PyOS_snprintf(buffer, sizeof(buffer), - name ? "" - : "", - self, - Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name, - PyWeakref_GET_OBJECT(self), - name); - Py_XDECREF(nameobj); - } - return PyString_FromString(buffer); -} - -/* Weak references only support equality, not ordering. Two weak references - are equal if the underlying objects are equal. If the underlying object has - gone away, they are equal if they are identical. */ - -static PyObject * -weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op) -{ - if (op != Py_EQ || self->ob_type != other->ob_type) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - if (PyWeakref_GET_OBJECT(self) == Py_None - || PyWeakref_GET_OBJECT(other) == Py_None) { - PyObject *res = self==other ? Py_True : Py_False; - Py_INCREF(res); - return res; - } - return PyObject_RichCompare(PyWeakref_GET_OBJECT(self), - PyWeakref_GET_OBJECT(other), op); -} - -/* Given the head of an object's list of weak references, extract the - * two callback-less refs (ref and proxy). Used to determine if the - * shared references exist and to determine the back link for newly - * inserted references. - */ -static void -get_basic_refs(PyWeakReference *head, - PyWeakReference **refp, PyWeakReference **proxyp) -{ - *refp = NULL; - *proxyp = NULL; - - if (head != NULL && head->wr_callback == NULL) { - /* We need to be careful that the "basic refs" aren't - subclasses of the main types. That complicates this a - little. */ - if (PyWeakref_CheckRefExact(head)) { - *refp = head; - head = head->wr_next; - } - if (head != NULL - && head->wr_callback == NULL - && PyWeakref_CheckProxy(head)) { - *proxyp = head; - /* head = head->wr_next; */ - } - } -} - -/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */ -static void -insert_after(PyWeakReference *newref, PyWeakReference *prev) -{ - newref->wr_prev = prev; - newref->wr_next = prev->wr_next; - if (prev->wr_next != NULL) - prev->wr_next->wr_prev = newref; - prev->wr_next = newref; -} - -/* Insert 'newref' at the head of the list; 'list' points to the variable - * that stores the head. - */ -static void -insert_head(PyWeakReference *newref, PyWeakReference **list) -{ - PyWeakReference *next = *list; - - newref->wr_prev = NULL; - newref->wr_next = next; - if (next != NULL) - next->wr_prev = newref; - *list = newref; -} - -static int -parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs, - PyObject **obp, PyObject **callbackp) -{ - /* XXX Should check that kwargs == NULL or is empty. */ - return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp); -} - -static PyObject * -weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyWeakReference *self = NULL; - PyObject *ob, *callback = NULL; - - if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) { - PyWeakReference *ref, *proxy; - PyWeakReference **list; - - if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { - PyErr_Format(PyExc_TypeError, - "cannot create weak reference to '%s' object", - Py_TYPE(ob)->tp_name); - return NULL; - } - if (callback == Py_None) - callback = NULL; - list = GET_WEAKREFS_LISTPTR(ob); - get_basic_refs(*list, &ref, &proxy); - if (callback == NULL && type == &_PyWeakref_RefType) { - if (ref != NULL) { - /* We can re-use an existing reference. */ - Py_INCREF(ref); - return (PyObject *)ref; - } - } - /* We have to create a new reference. */ - /* Note: the tp_alloc() can trigger cyclic GC, so the weakref - list on ob can be mutated. This means that the ref and - proxy pointers we got back earlier may have been collected, - so we need to compute these values again before we use - them. */ - self = (PyWeakReference *) (type->tp_alloc(type, 0)); - if (self != NULL) { - init_weakref(self, ob, callback); - if (callback == NULL && type == &_PyWeakref_RefType) { - insert_head(self, list); - } - else { - PyWeakReference *prev; - - get_basic_refs(*list, &ref, &proxy); - prev = (proxy == NULL) ? ref : proxy; - if (prev == NULL) - insert_head(self, list); - else - insert_after(self, prev); - } - } - } - return (PyObject *)self; -} - -static int -weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *tmp; - - if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp)) - return 0; - else - return -1; -} - - -PyTypeObject -_PyWeakref_RefType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "weakref", - sizeof(PyWeakReference), - 0, - weakref_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - (reprfunc)weakref_repr, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)weakref_hash, /*tp_hash*/ - (ternaryfunc)weakref_call, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE - | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc)gc_traverse, /*tp_traverse*/ - (inquiry)gc_clear, /*tp_clear*/ - (richcmpfunc)weakref_richcompare, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - weakref___init__, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - weakref___new__, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ -}; - - -static int -proxy_checkref(PyWeakReference *proxy) -{ - if (PyWeakref_GET_OBJECT(proxy) == Py_None) { - PyErr_SetString(PyExc_ReferenceError, - "weakly-referenced object no longer exists"); - return 0; - } - return 1; -} - - -/* If a parameter is a proxy, check that it is still "live" and wrap it, - * replacing the original value with the raw object. Raises ReferenceError - * if the param is a dead proxy. - */ -#define UNWRAP(o) \ - if (PyWeakref_CheckProxy(o)) { \ - if (!proxy_checkref((PyWeakReference *)o)) \ - return NULL; \ - o = PyWeakref_GET_OBJECT(o); \ - } - -#define UNWRAP_I(o) \ - if (PyWeakref_CheckProxy(o)) { \ - if (!proxy_checkref((PyWeakReference *)o)) \ - return -1; \ - o = PyWeakref_GET_OBJECT(o); \ - } - -#define WRAP_UNARY(method, generic) \ - static PyObject * \ - method(PyObject *proxy) { \ - UNWRAP(proxy); \ - return generic(proxy); \ - } - -#define WRAP_BINARY(method, generic) \ - static PyObject * \ - method(PyObject *x, PyObject *y) { \ - UNWRAP(x); \ - UNWRAP(y); \ - return generic(x, y); \ - } - -/* Note that the third arg needs to be checked for NULL since the tp_call - * slot can receive NULL for this arg. - */ -#define WRAP_TERNARY(method, generic) \ - static PyObject * \ - method(PyObject *proxy, PyObject *v, PyObject *w) { \ - UNWRAP(proxy); \ - UNWRAP(v); \ - if (w != NULL) \ - UNWRAP(w); \ - return generic(proxy, v, w); \ - } - -#define WRAP_METHOD(method, special) \ - static PyObject * \ - method(PyObject *proxy) { \ - UNWRAP(proxy); \ - return PyObject_CallMethod(proxy, special, ""); \ - } - - -/* direct slots */ - -WRAP_BINARY(proxy_getattr, PyObject_GetAttr) -WRAP_UNARY(proxy_str, PyObject_Str) -WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords) - -static PyObject * -proxy_repr(PyWeakReference *proxy) -{ - char buf[160]; - PyOS_snprintf(buf, sizeof(buf), - "", proxy, - Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name, - PyWeakref_GET_OBJECT(proxy)); - return PyString_FromString(buf); -} - - -static int -proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value) -{ - if (!proxy_checkref(proxy)) - return -1; - return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value); -} - -static int -proxy_compare(PyObject *proxy, PyObject *v) -{ - UNWRAP_I(proxy); - UNWRAP_I(v); - return PyObject_Compare(proxy, v); -} - -/* number slots */ -WRAP_BINARY(proxy_add, PyNumber_Add) -WRAP_BINARY(proxy_sub, PyNumber_Subtract) -WRAP_BINARY(proxy_mul, PyNumber_Multiply) -WRAP_BINARY(proxy_div, PyNumber_Divide) -WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide) -WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide) -WRAP_BINARY(proxy_mod, PyNumber_Remainder) -WRAP_BINARY(proxy_divmod, PyNumber_Divmod) -WRAP_TERNARY(proxy_pow, PyNumber_Power) -WRAP_UNARY(proxy_neg, PyNumber_Negative) -WRAP_UNARY(proxy_pos, PyNumber_Positive) -WRAP_UNARY(proxy_abs, PyNumber_Absolute) -WRAP_UNARY(proxy_invert, PyNumber_Invert) -WRAP_BINARY(proxy_lshift, PyNumber_Lshift) -WRAP_BINARY(proxy_rshift, PyNumber_Rshift) -WRAP_BINARY(proxy_and, PyNumber_And) -WRAP_BINARY(proxy_xor, PyNumber_Xor) -WRAP_BINARY(proxy_or, PyNumber_Or) -WRAP_UNARY(proxy_int, PyNumber_Int) -WRAP_UNARY(proxy_long, PyNumber_Long) -WRAP_UNARY(proxy_float, PyNumber_Float) -WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd) -WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract) -WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply) -WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide) -WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide) -WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide) -WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder) -WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower) -WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift) -WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift) -WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd) -WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor) -WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) -WRAP_UNARY(proxy_index, PyNumber_Index) - -static int -proxy_nonzero(PyWeakReference *proxy) -{ - PyObject *o = PyWeakref_GET_OBJECT(proxy); - if (!proxy_checkref(proxy)) - return -1; - return PyObject_IsTrue(o); -} - -static void -proxy_dealloc(PyWeakReference *self) -{ - if (self->wr_callback != NULL) - PyObject_GC_UnTrack((PyObject *)self); - clear_weakref(self); - PyObject_GC_Del(self); -} - -/* sequence slots */ - -static PyObject * -proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j) -{ - if (!proxy_checkref(proxy)) - return NULL; - return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j); -} - -static int -proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value) -{ - if (!proxy_checkref(proxy)) - return -1; - return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value); -} - -static int -proxy_contains(PyWeakReference *proxy, PyObject *value) -{ - if (!proxy_checkref(proxy)) - return -1; - return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value); -} - - -/* mapping slots */ - -static Py_ssize_t -proxy_length(PyWeakReference *proxy) -{ - if (!proxy_checkref(proxy)) - return -1; - return PyObject_Length(PyWeakref_GET_OBJECT(proxy)); -} - -WRAP_BINARY(proxy_getitem, PyObject_GetItem) - -static int -proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value) -{ - if (!proxy_checkref(proxy)) - return -1; - - if (value == NULL) - return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key); - else - return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value); -} - -/* iterator slots */ - -static PyObject * -proxy_iter(PyWeakReference *proxy) -{ - if (!proxy_checkref(proxy)) - return NULL; - return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy)); -} - -static PyObject * -proxy_iternext(PyWeakReference *proxy) -{ - if (!proxy_checkref(proxy)) - return NULL; - return PyIter_Next(PyWeakref_GET_OBJECT(proxy)); -} - - -WRAP_METHOD(proxy_unicode, "__unicode__"); - - -static PyMethodDef proxy_methods[] = { - {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS}, - {NULL, NULL} -}; - - -static PyNumberMethods proxy_as_number = { - proxy_add, /*nb_add*/ - proxy_sub, /*nb_subtract*/ - proxy_mul, /*nb_multiply*/ - proxy_div, /*nb_divide*/ - proxy_mod, /*nb_remainder*/ - proxy_divmod, /*nb_divmod*/ - proxy_pow, /*nb_power*/ - proxy_neg, /*nb_negative*/ - proxy_pos, /*nb_positive*/ - proxy_abs, /*nb_absolute*/ - (inquiry)proxy_nonzero, /*nb_nonzero*/ - proxy_invert, /*nb_invert*/ - proxy_lshift, /*nb_lshift*/ - proxy_rshift, /*nb_rshift*/ - proxy_and, /*nb_and*/ - proxy_xor, /*nb_xor*/ - proxy_or, /*nb_or*/ - 0, /*nb_coerce*/ - proxy_int, /*nb_int*/ - proxy_long, /*nb_long*/ - proxy_float, /*nb_float*/ - 0, /*nb_oct*/ - 0, /*nb_hex*/ - proxy_iadd, /*nb_inplace_add*/ - proxy_isub, /*nb_inplace_subtract*/ - proxy_imul, /*nb_inplace_multiply*/ - proxy_idiv, /*nb_inplace_divide*/ - proxy_imod, /*nb_inplace_remainder*/ - proxy_ipow, /*nb_inplace_power*/ - proxy_ilshift, /*nb_inplace_lshift*/ - proxy_irshift, /*nb_inplace_rshift*/ - proxy_iand, /*nb_inplace_and*/ - proxy_ixor, /*nb_inplace_xor*/ - proxy_ior, /*nb_inplace_or*/ - proxy_floor_div, /*nb_floor_divide*/ - proxy_true_div, /*nb_true_divide*/ - proxy_ifloor_div, /*nb_inplace_floor_divide*/ - proxy_itrue_div, /*nb_inplace_true_divide*/ - proxy_index, /*nb_index*/ -}; - -static PySequenceMethods proxy_as_sequence = { - (lenfunc)proxy_length, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - 0, /*sq_item*/ - (ssizessizeargfunc)proxy_slice, /*sq_slice*/ - 0, /*sq_ass_item*/ - (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/ - (objobjproc)proxy_contains, /* sq_contains */ -}; - -static PyMappingMethods proxy_as_mapping = { - (lenfunc)proxy_length, /*mp_length*/ - proxy_getitem, /*mp_subscript*/ - (objobjargproc)proxy_setitem, /*mp_ass_subscript*/ -}; - - -PyTypeObject -_PyWeakref_ProxyType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "weakproxy", - sizeof(PyWeakReference), - 0, - /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - proxy_compare, /* tp_compare */ - (reprfunc)proxy_repr, /* tp_repr */ - &proxy_as_number, /* tp_as_number */ - &proxy_as_sequence, /* tp_as_sequence */ - &proxy_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - proxy_str, /* tp_str */ - proxy_getattr, /* tp_getattro */ - (setattrofunc)proxy_setattr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)gc_traverse, /* tp_traverse */ - (inquiry)gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)proxy_iter, /* tp_iter */ - (iternextfunc)proxy_iternext, /* tp_iternext */ - proxy_methods, /* tp_methods */ -}; - - -PyTypeObject -_PyWeakref_CallableProxyType = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "weakcallableproxy", - sizeof(PyWeakReference), - 0, - /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - proxy_compare, /* tp_compare */ - (unaryfunc)proxy_repr, /* tp_repr */ - &proxy_as_number, /* tp_as_number */ - &proxy_as_sequence, /* tp_as_sequence */ - &proxy_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - proxy_call, /* tp_call */ - proxy_str, /* tp_str */ - proxy_getattr, /* tp_getattro */ - (setattrofunc)proxy_setattr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC - | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)gc_traverse, /* tp_traverse */ - (inquiry)gc_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)proxy_iter, /* tp_iter */ - (iternextfunc)proxy_iternext, /* tp_iternext */ -}; - - - -PyObject * -PyWeakref_NewRef(PyObject *ob, PyObject *callback) -{ - PyWeakReference *result = NULL; - PyWeakReference **list; - PyWeakReference *ref, *proxy; - - if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { - PyErr_Format(PyExc_TypeError, - "cannot create weak reference to '%s' object", - Py_TYPE(ob)->tp_name); - return NULL; - } - list = GET_WEAKREFS_LISTPTR(ob); - get_basic_refs(*list, &ref, &proxy); - if (callback == Py_None) - callback = NULL; - if (callback == NULL) - /* return existing weak reference if it exists */ - result = ref; - if (result != NULL) - Py_INCREF(result); - else { - /* Note: new_weakref() can trigger cyclic GC, so the weakref - list on ob can be mutated. This means that the ref and - proxy pointers we got back earlier may have been collected, - so we need to compute these values again before we use - them. */ - result = new_weakref(ob, callback); - if (result != NULL) { - get_basic_refs(*list, &ref, &proxy); - if (callback == NULL) { - if (ref == NULL) - insert_head(result, list); - else { - /* Someone else added a ref without a callback - during GC. Return that one instead of this one - to avoid violating the invariants of the list - of weakrefs for ob. */ - Py_DECREF(result); - Py_INCREF(ref); - result = ref; - } - } - else { - PyWeakReference *prev; - - prev = (proxy == NULL) ? ref : proxy; - if (prev == NULL) - insert_head(result, list); - else - insert_after(result, prev); - } - } - } - return (PyObject *) result; -} - - -PyObject * -PyWeakref_NewProxy(PyObject *ob, PyObject *callback) -{ - PyWeakReference *result = NULL; - PyWeakReference **list; - PyWeakReference *ref, *proxy; - - if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { - PyErr_Format(PyExc_TypeError, - "cannot create weak reference to '%s' object", - Py_TYPE(ob)->tp_name); - return NULL; - } - list = GET_WEAKREFS_LISTPTR(ob); - get_basic_refs(*list, &ref, &proxy); - if (callback == Py_None) - callback = NULL; - if (callback == NULL) - /* attempt to return an existing weak reference if it exists */ - result = proxy; - if (result != NULL) - Py_INCREF(result); - else { - /* Note: new_weakref() can trigger cyclic GC, so the weakref - list on ob can be mutated. This means that the ref and - proxy pointers we got back earlier may have been collected, - so we need to compute these values again before we use - them. */ - result = new_weakref(ob, callback); - if (result != NULL) { - PyWeakReference *prev; - - if (PyCallable_Check(ob)) - Py_TYPE(result) = &_PyWeakref_CallableProxyType; - else - Py_TYPE(result) = &_PyWeakref_ProxyType; - get_basic_refs(*list, &ref, &proxy); - if (callback == NULL) { - if (proxy != NULL) { - /* Someone else added a proxy without a callback - during GC. Return that one instead of this one - to avoid violating the invariants of the list - of weakrefs for ob. */ - Py_DECREF(result); - Py_INCREF(result = proxy); - goto skip_insert; - } - prev = ref; - } - else - prev = (proxy == NULL) ? ref : proxy; - - if (prev == NULL) - insert_head(result, list); - else - insert_after(result, prev); - skip_insert: - ; - } - } - return (PyObject *) result; -} - - -PyObject * -PyWeakref_GetObject(PyObject *ref) -{ - if (ref == NULL || !PyWeakref_Check(ref)) { - PyErr_BadInternalCall(); - return NULL; - } - return PyWeakref_GET_OBJECT(ref); -} - -/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's - * handle_weakrefs(). - */ -static void -handle_callback(PyWeakReference *ref, PyObject *callback) -{ - PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL); - - if (cbresult == NULL) - PyErr_WriteUnraisable(callback); - else - Py_DECREF(cbresult); -} - -/* This function is called by the tp_dealloc handler to clear weak references. - * - * This iterates through the weak references for 'object' and calls callbacks - * for those references which have one. It returns when all callbacks have - * been attempted. - */ -void -PyObject_ClearWeakRefs(PyObject *object) -{ - PyWeakReference **list; - - if (object == NULL - || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)) - || object->ob_refcnt != 0) { - PyErr_BadInternalCall(); - return; - } - list = GET_WEAKREFS_LISTPTR(object); - /* Remove the callback-less basic and proxy references */ - if (*list != NULL && (*list)->wr_callback == NULL) { - clear_weakref(*list); - if (*list != NULL && (*list)->wr_callback == NULL) - clear_weakref(*list); - } - if (*list != NULL) { - PyWeakReference *current = *list; - Py_ssize_t count = _PyWeakref_GetWeakrefCount(current); - int restore_error = PyErr_Occurred() ? 1 : 0; - PyObject *err_type = NULL, - *err_value = NULL, - *err_tb = NULL; - - if (restore_error) - PyErr_Fetch(&err_type, &err_value, &err_tb); - if (count == 1) { - PyObject *callback = current->wr_callback; - - current->wr_callback = NULL; - clear_weakref(current); - if (callback != NULL) { - if (current->ob_refcnt > 0) - handle_callback(current, callback); - Py_DECREF(callback); - } - } - else { - PyObject *tuple; - Py_ssize_t i = 0; - - tuple = PyTuple_New(count * 2); - if (tuple == NULL) { - if (restore_error) - PyErr_Fetch(&err_type, &err_value, &err_tb); - return; - } - - for (i = 0; i < count; ++i) { - PyWeakReference *next = current->wr_next; - - if (current->ob_refcnt > 0) - { - Py_INCREF(current); - PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); - PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); - } - else { - Py_DECREF(current->wr_callback); - } - current->wr_callback = NULL; - clear_weakref(current); - current = next; - } - for (i = 0; i < count; ++i) { - PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); - - /* The tuple may have slots left to NULL */ - if (callback != NULL) { - PyObject *item = PyTuple_GET_ITEM(tuple, i * 2); - handle_callback((PyWeakReference *)item, callback); - } - } - Py_DECREF(tuple); - } - if (restore_error) - PyErr_Restore(err_type, err_value, err_tb); - } -}