Home | History | Annotate | Download | only in Objects
      1 #include "Python.h"
      2 #include "structmember.h"
      3 
      4 
      5 #define GET_WEAKREFS_LISTPTR(o) \
      6         ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
      7 
      8 
      9 Py_ssize_t
     10 _PyWeakref_GetWeakrefCount(PyWeakReference *head)
     11 {
     12     Py_ssize_t count = 0;
     13 
     14     while (head != NULL) {
     15         ++count;
     16         head = head->wr_next;
     17     }
     18     return count;
     19 }
     20 
     21 
     22 static void
     23 init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
     24 {
     25     self->hash = -1;
     26     self->wr_object = ob;
     27     Py_XINCREF(callback);
     28     self->wr_callback = callback;
     29 }
     30 
     31 static PyWeakReference *
     32 new_weakref(PyObject *ob, PyObject *callback)
     33 {
     34     PyWeakReference *result;
     35 
     36     result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
     37     if (result) {
     38         init_weakref(result, ob, callback);
     39         PyObject_GC_Track(result);
     40     }
     41     return result;
     42 }
     43 
     44 
     45 /* This function clears the passed-in reference and removes it from the
     46  * list of weak references for the referent.  This is the only code that
     47  * removes an item from the doubly-linked list of weak references for an
     48  * object; it is also responsible for clearing the callback slot.
     49  */
     50 static void
     51 clear_weakref(PyWeakReference *self)
     52 {
     53     PyObject *callback = self->wr_callback;
     54 
     55     if (self->wr_object != Py_None) {
     56         PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
     57 
     58         if (*list == self)
     59             /* If 'self' is the end of the list (and thus self->wr_next == NULL)
     60                then the weakref list itself (and thus the value of *list) will
     61                end up being set to NULL. */
     62             *list = self->wr_next;
     63         self->wr_object = Py_None;
     64         if (self->wr_prev != NULL)
     65             self->wr_prev->wr_next = self->wr_next;
     66         if (self->wr_next != NULL)
     67             self->wr_next->wr_prev = self->wr_prev;
     68         self->wr_prev = NULL;
     69         self->wr_next = NULL;
     70     }
     71     if (callback != NULL) {
     72         Py_DECREF(callback);
     73         self->wr_callback = NULL;
     74     }
     75 }
     76 
     77 /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
     78  * the callback intact and uncalled.  It must be possible to call self's
     79  * tp_dealloc() after calling this, so self has to be left in a sane enough
     80  * state for that to work.  We expect tp_dealloc to decref the callback
     81  * then.  The reason for not letting clear_weakref() decref the callback
     82  * right now is that if the callback goes away, that may in turn trigger
     83  * another callback (if a weak reference to the callback exists) -- running
     84  * arbitrary Python code in the middle of gc is a disaster.  The convolution
     85  * here allows gc to delay triggering such callbacks until the world is in
     86  * a sane state again.
     87  */
     88 void
     89 _PyWeakref_ClearRef(PyWeakReference *self)
     90 {
     91     PyObject *callback;
     92 
     93     assert(self != NULL);
     94     assert(PyWeakref_Check(self));
     95     /* Preserve and restore the callback around clear_weakref. */
     96     callback = self->wr_callback;
     97     self->wr_callback = NULL;
     98     clear_weakref(self);
     99     self->wr_callback = callback;
    100 }
    101 
    102 static void
    103 weakref_dealloc(PyObject *self)
    104 {
    105     PyObject_GC_UnTrack(self);
    106     clear_weakref((PyWeakReference *) self);
    107     Py_TYPE(self)->tp_free(self);
    108 }
    109 
    110 
    111 static int
    112 gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
    113 {
    114     Py_VISIT(self->wr_callback);
    115     return 0;
    116 }
    117 
    118 
    119 static int
    120 gc_clear(PyWeakReference *self)
    121 {
    122     clear_weakref(self);
    123     return 0;
    124 }
    125 
    126 
    127 static PyObject *
    128 weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
    129 {
    130     static char *kwlist[] = {NULL};
    131 
    132     if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
    133         PyObject *object = PyWeakref_GET_OBJECT(self);
    134         Py_INCREF(object);
    135         return (object);
    136     }
    137     return NULL;
    138 }
    139 
    140 
    141 static long
    142 weakref_hash(PyWeakReference *self)
    143 {
    144     if (self->hash != -1)
    145         return self->hash;
    146     if (PyWeakref_GET_OBJECT(self) == Py_None) {
    147         PyErr_SetString(PyExc_TypeError, "weak object has gone away");
    148         return -1;
    149     }
    150     self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
    151     return self->hash;
    152 }
    153 
    154 
    155 static PyObject *
    156 weakref_repr(PyWeakReference *self)
    157 {
    158     char buffer[256];
    159     if (PyWeakref_GET_OBJECT(self) == Py_None) {
    160         PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
    161     }
    162     else {
    163         char *name = NULL;
    164         PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
    165                                                    "__name__");
    166         if (nameobj == NULL)
    167                 PyErr_Clear();
    168         else if (PyString_Check(nameobj))
    169                 name = PyString_AS_STRING(nameobj);
    170         if (name != NULL) {
    171             PyOS_snprintf(buffer, sizeof(buffer),
    172                           "<weakref at %p; to '%.50s' at %p (%s)>",
    173                           self,
    174                           Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
    175                           PyWeakref_GET_OBJECT(self),
    176                           name);
    177         }
    178         else {
    179             PyOS_snprintf(buffer, sizeof(buffer),
    180                           "<weakref at %p; to '%.50s' at %p>",
    181                           self,
    182                           Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
    183                           PyWeakref_GET_OBJECT(self));
    184         }
    185         Py_XDECREF(nameobj);
    186     }
    187     return PyString_FromString(buffer);
    188 }
    189 
    190 /* Weak references only support equality, not ordering. Two weak references
    191    are equal if the underlying objects are equal. If the underlying object has
    192    gone away, they are equal if they are identical. */
    193 
    194 static PyObject *
    195 weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
    196 {
    197     if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
    198         Py_INCREF(Py_NotImplemented);
    199         return Py_NotImplemented;
    200     }
    201     if (PyWeakref_GET_OBJECT(self) == Py_None
    202         || PyWeakref_GET_OBJECT(other) == Py_None) {
    203         int res = (self == other);
    204         if (op == Py_NE)
    205             res = !res;
    206         if (res)
    207             Py_RETURN_TRUE;
    208         else
    209             Py_RETURN_FALSE;
    210     }
    211     return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
    212                                 PyWeakref_GET_OBJECT(other), op);
    213 }
    214 
    215 /* Given the head of an object's list of weak references, extract the
    216  * two callback-less refs (ref and proxy).  Used to determine if the
    217  * shared references exist and to determine the back link for newly
    218  * inserted references.
    219  */
    220 static void
    221 get_basic_refs(PyWeakReference *head,
    222                PyWeakReference **refp, PyWeakReference **proxyp)
    223 {
    224     *refp = NULL;
    225     *proxyp = NULL;
    226 
    227     if (head != NULL && head->wr_callback == NULL) {
    228         /* We need to be careful that the "basic refs" aren't
    229            subclasses of the main types.  That complicates this a
    230            little. */
    231         if (PyWeakref_CheckRefExact(head)) {
    232             *refp = head;
    233             head = head->wr_next;
    234         }
    235         if (head != NULL
    236             && head->wr_callback == NULL
    237             && PyWeakref_CheckProxy(head)) {
    238             *proxyp = head;
    239             /* head = head->wr_next; */
    240         }
    241     }
    242 }
    243 
    244 /* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */
    245 static void
    246 insert_after(PyWeakReference *newref, PyWeakReference *prev)
    247 {
    248     newref->wr_prev = prev;
    249     newref->wr_next = prev->wr_next;
    250     if (prev->wr_next != NULL)
    251         prev->wr_next->wr_prev = newref;
    252     prev->wr_next = newref;
    253 }
    254 
    255 /* Insert 'newref' at the head of the list; 'list' points to the variable
    256  * that stores the head.
    257  */
    258 static void
    259 insert_head(PyWeakReference *newref, PyWeakReference **list)
    260 {
    261     PyWeakReference *next = *list;
    262 
    263     newref->wr_prev = NULL;
    264     newref->wr_next = next;
    265     if (next != NULL)
    266         next->wr_prev = newref;
    267     *list = newref;
    268 }
    269 
    270 static int
    271 parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
    272                         PyObject **obp, PyObject **callbackp)
    273 {
    274     return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
    275 }
    276 
    277 static PyObject *
    278 weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    279 {
    280     PyWeakReference *self = NULL;
    281     PyObject *ob, *callback = NULL;
    282 
    283     if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
    284         PyWeakReference *ref, *proxy;
    285         PyWeakReference **list;
    286 
    287         if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
    288             PyErr_Format(PyExc_TypeError,
    289                          "cannot create weak reference to '%s' object",
    290                          Py_TYPE(ob)->tp_name);
    291             return NULL;
    292         }
    293         if (callback == Py_None)
    294             callback = NULL;
    295         list = GET_WEAKREFS_LISTPTR(ob);
    296         get_basic_refs(*list, &ref, &proxy);
    297         if (callback == NULL && type == &_PyWeakref_RefType) {
    298             if (ref != NULL) {
    299                 /* We can re-use an existing reference. */
    300                 Py_INCREF(ref);
    301                 return (PyObject *)ref;
    302             }
    303         }
    304         /* We have to create a new reference. */
    305         /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
    306            list on ob can be mutated.  This means that the ref and
    307            proxy pointers we got back earlier may have been collected,
    308            so we need to compute these values again before we use
    309            them. */
    310         self = (PyWeakReference *) (type->tp_alloc(type, 0));
    311         if (self != NULL) {
    312             init_weakref(self, ob, callback);
    313             if (callback == NULL && type == &_PyWeakref_RefType) {
    314                 insert_head(self, list);
    315             }
    316             else {
    317                 PyWeakReference *prev;
    318 
    319                 get_basic_refs(*list, &ref, &proxy);
    320                 prev = (proxy == NULL) ? ref : proxy;
    321                 if (prev == NULL)
    322                     insert_head(self, list);
    323                 else
    324                     insert_after(self, prev);
    325             }
    326         }
    327     }
    328     return (PyObject *)self;
    329 }
    330 
    331 static int
    332 weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
    333 {
    334     PyObject *tmp;
    335 
    336     if (!_PyArg_NoKeywords("ref()", kwargs))
    337         return -1;
    338 
    339     if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
    340         return 0;
    341     else
    342         return -1;
    343 }
    344 
    345 
    346 PyTypeObject
    347 _PyWeakref_RefType = {
    348     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    349     "weakref",
    350     sizeof(PyWeakReference),
    351     0,
    352     weakref_dealloc,            /*tp_dealloc*/
    353     0,                          /*tp_print*/
    354     0,                          /*tp_getattr*/
    355     0,                          /*tp_setattr*/
    356     0,                          /*tp_compare*/
    357     (reprfunc)weakref_repr,     /*tp_repr*/
    358     0,                          /*tp_as_number*/
    359     0,                          /*tp_as_sequence*/
    360     0,                          /*tp_as_mapping*/
    361     (hashfunc)weakref_hash,     /*tp_hash*/
    362     (ternaryfunc)weakref_call,  /*tp_call*/
    363     0,                          /*tp_str*/
    364     0,                          /*tp_getattro*/
    365     0,                          /*tp_setattro*/
    366     0,                          /*tp_as_buffer*/
    367     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
    368         | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
    369     0,                          /*tp_doc*/
    370     (traverseproc)gc_traverse,  /*tp_traverse*/
    371     (inquiry)gc_clear,          /*tp_clear*/
    372     (richcmpfunc)weakref_richcompare,   /*tp_richcompare*/
    373     0,                          /*tp_weaklistoffset*/
    374     0,                          /*tp_iter*/
    375     0,                          /*tp_iternext*/
    376     0,                          /*tp_methods*/
    377     0,                          /*tp_members*/
    378     0,                          /*tp_getset*/
    379     0,                          /*tp_base*/
    380     0,                          /*tp_dict*/
    381     0,                          /*tp_descr_get*/
    382     0,                          /*tp_descr_set*/
    383     0,                          /*tp_dictoffset*/
    384     weakref___init__,           /*tp_init*/
    385     PyType_GenericAlloc,        /*tp_alloc*/
    386     weakref___new__,            /*tp_new*/
    387     PyObject_GC_Del,            /*tp_free*/
    388 };
    389 
    390 
    391 static int
    392 proxy_checkref(PyWeakReference *proxy)
    393 {
    394     if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
    395         PyErr_SetString(PyExc_ReferenceError,
    396                         "weakly-referenced object no longer exists");
    397         return 0;
    398     }
    399     return 1;
    400 }
    401 
    402 
    403 /* If a parameter is a proxy, check that it is still "live" and wrap it,
    404  * replacing the original value with the raw object.  Raises ReferenceError
    405  * if the param is a dead proxy.
    406  */
    407 #define UNWRAP(o) \
    408         if (PyWeakref_CheckProxy(o)) { \
    409             if (!proxy_checkref((PyWeakReference *)o)) \
    410                 return NULL; \
    411             o = PyWeakref_GET_OBJECT(o); \
    412         }
    413 
    414 #define UNWRAP_I(o) \
    415         if (PyWeakref_CheckProxy(o)) { \
    416             if (!proxy_checkref((PyWeakReference *)o)) \
    417                 return -1; \
    418             o = PyWeakref_GET_OBJECT(o); \
    419         }
    420 
    421 #define WRAP_UNARY(method, generic) \
    422     static PyObject * \
    423     method(PyObject *proxy) { \
    424         UNWRAP(proxy); \
    425         return generic(proxy); \
    426     }
    427 
    428 #define WRAP_BINARY(method, generic) \
    429     static PyObject * \
    430     method(PyObject *x, PyObject *y) { \
    431         UNWRAP(x); \
    432         UNWRAP(y); \
    433         return generic(x, y); \
    434     }
    435 
    436 /* Note that the third arg needs to be checked for NULL since the tp_call
    437  * slot can receive NULL for this arg.
    438  */
    439 #define WRAP_TERNARY(method, generic) \
    440     static PyObject * \
    441     method(PyObject *proxy, PyObject *v, PyObject *w) { \
    442         UNWRAP(proxy); \
    443         UNWRAP(v); \
    444         if (w != NULL) \
    445             UNWRAP(w); \
    446         return generic(proxy, v, w); \
    447     }
    448 
    449 #define WRAP_METHOD(method, special) \
    450     static PyObject * \
    451     method(PyObject *proxy) { \
    452             UNWRAP(proxy); \
    453                 return PyObject_CallMethod(proxy, special, ""); \
    454         }
    455 
    456 
    457 /* direct slots */
    458 
    459 WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
    460 WRAP_UNARY(proxy_str, PyObject_Str)
    461 WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
    462 
    463 static PyObject *
    464 proxy_repr(PyWeakReference *proxy)
    465 {
    466     char buf[160];
    467     PyOS_snprintf(buf, sizeof(buf),
    468                   "<weakproxy at %p to %.100s at %p>", proxy,
    469                   Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
    470                   PyWeakref_GET_OBJECT(proxy));
    471     return PyString_FromString(buf);
    472 }
    473 
    474 
    475 static int
    476 proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
    477 {
    478     if (!proxy_checkref(proxy))
    479         return -1;
    480     return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
    481 }
    482 
    483 static int
    484 proxy_compare(PyObject *proxy, PyObject *v)
    485 {
    486     UNWRAP_I(proxy);
    487     UNWRAP_I(v);
    488     return PyObject_Compare(proxy, v);
    489 }
    490 
    491 /* number slots */
    492 WRAP_BINARY(proxy_add, PyNumber_Add)
    493 WRAP_BINARY(proxy_sub, PyNumber_Subtract)
    494 WRAP_BINARY(proxy_mul, PyNumber_Multiply)
    495 WRAP_BINARY(proxy_div, PyNumber_Divide)
    496 WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
    497 WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
    498 WRAP_BINARY(proxy_mod, PyNumber_Remainder)
    499 WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
    500 WRAP_TERNARY(proxy_pow, PyNumber_Power)
    501 WRAP_UNARY(proxy_neg, PyNumber_Negative)
    502 WRAP_UNARY(proxy_pos, PyNumber_Positive)
    503 WRAP_UNARY(proxy_abs, PyNumber_Absolute)
    504 WRAP_UNARY(proxy_invert, PyNumber_Invert)
    505 WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
    506 WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
    507 WRAP_BINARY(proxy_and, PyNumber_And)
    508 WRAP_BINARY(proxy_xor, PyNumber_Xor)
    509 WRAP_BINARY(proxy_or, PyNumber_Or)
    510 WRAP_UNARY(proxy_int, PyNumber_Int)
    511 WRAP_UNARY(proxy_long, PyNumber_Long)
    512 WRAP_UNARY(proxy_float, PyNumber_Float)
    513 WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
    514 WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
    515 WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
    516 WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
    517 WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
    518 WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
    519 WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
    520 WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
    521 WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
    522 WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
    523 WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
    524 WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
    525 WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
    526 WRAP_UNARY(proxy_index, PyNumber_Index)
    527 
    528 static int
    529 proxy_nonzero(PyWeakReference *proxy)
    530 {
    531     PyObject *o = PyWeakref_GET_OBJECT(proxy);
    532     if (!proxy_checkref(proxy))
    533         return -1;
    534     return PyObject_IsTrue(o);
    535 }
    536 
    537 static void
    538 proxy_dealloc(PyWeakReference *self)
    539 {
    540     if (self->wr_callback != NULL)
    541         PyObject_GC_UnTrack((PyObject *)self);
    542     clear_weakref(self);
    543     PyObject_GC_Del(self);
    544 }
    545 
    546 /* sequence slots */
    547 
    548 static PyObject *
    549 proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
    550 {
    551     if (!proxy_checkref(proxy))
    552         return NULL;
    553     return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
    554 }
    555 
    556 static int
    557 proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
    558 {
    559     if (!proxy_checkref(proxy))
    560         return -1;
    561     return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
    562 }
    563 
    564 static int
    565 proxy_contains(PyWeakReference *proxy, PyObject *value)
    566 {
    567     if (!proxy_checkref(proxy))
    568         return -1;
    569     return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
    570 }
    571 
    572 
    573 /* mapping slots */
    574 
    575 static Py_ssize_t
    576 proxy_length(PyWeakReference *proxy)
    577 {
    578     if (!proxy_checkref(proxy))
    579         return -1;
    580     return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
    581 }
    582 
    583 WRAP_BINARY(proxy_getitem, PyObject_GetItem)
    584 
    585 static int
    586 proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
    587 {
    588     if (!proxy_checkref(proxy))
    589         return -1;
    590 
    591     if (value == NULL)
    592         return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
    593     else
    594         return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
    595 }
    596 
    597 /* iterator slots */
    598 
    599 static PyObject *
    600 proxy_iter(PyWeakReference *proxy)
    601 {
    602     if (!proxy_checkref(proxy))
    603         return NULL;
    604     return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
    605 }
    606 
    607 static PyObject *
    608 proxy_iternext(PyWeakReference *proxy)
    609 {
    610     if (!proxy_checkref(proxy))
    611         return NULL;
    612     return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
    613 }
    614 
    615 
    616 WRAP_METHOD(proxy_unicode, "__unicode__");
    617 
    618 
    619 static PyMethodDef proxy_methods[] = {
    620         {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
    621         {NULL, NULL}
    622 };
    623 
    624 
    625 static PyNumberMethods proxy_as_number = {
    626     proxy_add,              /*nb_add*/
    627     proxy_sub,              /*nb_subtract*/
    628     proxy_mul,              /*nb_multiply*/
    629     proxy_div,              /*nb_divide*/
    630     proxy_mod,              /*nb_remainder*/
    631     proxy_divmod,           /*nb_divmod*/
    632     proxy_pow,              /*nb_power*/
    633     proxy_neg,              /*nb_negative*/
    634     proxy_pos,              /*nb_positive*/
    635     proxy_abs,              /*nb_absolute*/
    636     (inquiry)proxy_nonzero, /*nb_nonzero*/
    637     proxy_invert,           /*nb_invert*/
    638     proxy_lshift,           /*nb_lshift*/
    639     proxy_rshift,           /*nb_rshift*/
    640     proxy_and,              /*nb_and*/
    641     proxy_xor,              /*nb_xor*/
    642     proxy_or,               /*nb_or*/
    643     0,                      /*nb_coerce*/
    644     proxy_int,              /*nb_int*/
    645     proxy_long,             /*nb_long*/
    646     proxy_float,            /*nb_float*/
    647     0,                      /*nb_oct*/
    648     0,                      /*nb_hex*/
    649     proxy_iadd,             /*nb_inplace_add*/
    650     proxy_isub,             /*nb_inplace_subtract*/
    651     proxy_imul,             /*nb_inplace_multiply*/
    652     proxy_idiv,             /*nb_inplace_divide*/
    653     proxy_imod,             /*nb_inplace_remainder*/
    654     proxy_ipow,             /*nb_inplace_power*/
    655     proxy_ilshift,          /*nb_inplace_lshift*/
    656     proxy_irshift,          /*nb_inplace_rshift*/
    657     proxy_iand,             /*nb_inplace_and*/
    658     proxy_ixor,             /*nb_inplace_xor*/
    659     proxy_ior,              /*nb_inplace_or*/
    660     proxy_floor_div,        /*nb_floor_divide*/
    661     proxy_true_div,         /*nb_true_divide*/
    662     proxy_ifloor_div,       /*nb_inplace_floor_divide*/
    663     proxy_itrue_div,        /*nb_inplace_true_divide*/
    664     proxy_index,            /*nb_index*/
    665 };
    666 
    667 static PySequenceMethods proxy_as_sequence = {
    668     (lenfunc)proxy_length,      /*sq_length*/
    669     0,                          /*sq_concat*/
    670     0,                          /*sq_repeat*/
    671     0,                          /*sq_item*/
    672     (ssizessizeargfunc)proxy_slice, /*sq_slice*/
    673     0,                          /*sq_ass_item*/
    674     (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
    675     (objobjproc)proxy_contains, /* sq_contains */
    676 };
    677 
    678 static PyMappingMethods proxy_as_mapping = {
    679     (lenfunc)proxy_length,        /*mp_length*/
    680     proxy_getitem,                /*mp_subscript*/
    681     (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
    682 };
    683 
    684 
    685 PyTypeObject
    686 _PyWeakref_ProxyType = {
    687     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    688     "weakproxy",
    689     sizeof(PyWeakReference),
    690     0,
    691     /* methods */
    692     (destructor)proxy_dealloc,          /* tp_dealloc */
    693     0,                                  /* tp_print */
    694     0,                                  /* tp_getattr */
    695     0,                                  /* tp_setattr */
    696     proxy_compare,                      /* tp_compare */
    697     (reprfunc)proxy_repr,               /* tp_repr */
    698     &proxy_as_number,                   /* tp_as_number */
    699     &proxy_as_sequence,                 /* tp_as_sequence */
    700     &proxy_as_mapping,                  /* tp_as_mapping */
    701     0,                                  /* tp_hash */
    702     0,                                  /* tp_call */
    703     proxy_str,                          /* tp_str */
    704     proxy_getattr,                      /* tp_getattro */
    705     (setattrofunc)proxy_setattr,        /* tp_setattro */
    706     0,                                  /* tp_as_buffer */
    707     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
    708     | Py_TPFLAGS_CHECKTYPES,            /* tp_flags */
    709     0,                                  /* tp_doc */
    710     (traverseproc)gc_traverse,          /* tp_traverse */
    711     (inquiry)gc_clear,                  /* tp_clear */
    712     0,                                  /* tp_richcompare */
    713     0,                                  /* tp_weaklistoffset */
    714     (getiterfunc)proxy_iter,            /* tp_iter */
    715     (iternextfunc)proxy_iternext,       /* tp_iternext */
    716         proxy_methods,                      /* tp_methods */
    717 };
    718 
    719 
    720 PyTypeObject
    721 _PyWeakref_CallableProxyType = {
    722     PyVarObject_HEAD_INIT(&PyType_Type, 0)
    723     "weakcallableproxy",
    724     sizeof(PyWeakReference),
    725     0,
    726     /* methods */
    727     (destructor)proxy_dealloc,          /* tp_dealloc */
    728     0,                                  /* tp_print */
    729     0,                                  /* tp_getattr */
    730     0,                                  /* tp_setattr */
    731     proxy_compare,                      /* tp_compare */
    732     (unaryfunc)proxy_repr,              /* tp_repr */
    733     &proxy_as_number,                   /* tp_as_number */
    734     &proxy_as_sequence,                 /* tp_as_sequence */
    735     &proxy_as_mapping,                  /* tp_as_mapping */
    736     0,                                  /* tp_hash */
    737     proxy_call,                         /* tp_call */
    738     proxy_str,                          /* tp_str */
    739     proxy_getattr,                      /* tp_getattro */
    740     (setattrofunc)proxy_setattr,        /* tp_setattro */
    741     0,                                  /* tp_as_buffer */
    742     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
    743     | Py_TPFLAGS_CHECKTYPES,            /* tp_flags */
    744     0,                                  /* tp_doc */
    745     (traverseproc)gc_traverse,          /* tp_traverse */
    746     (inquiry)gc_clear,                  /* tp_clear */
    747     0,                                  /* tp_richcompare */
    748     0,                                  /* tp_weaklistoffset */
    749     (getiterfunc)proxy_iter,            /* tp_iter */
    750     (iternextfunc)proxy_iternext,       /* tp_iternext */
    751 };
    752 
    753 
    754 
    755 PyObject *
    756 PyWeakref_NewRef(PyObject *ob, PyObject *callback)
    757 {
    758     PyWeakReference *result = NULL;
    759     PyWeakReference **list;
    760     PyWeakReference *ref, *proxy;
    761 
    762     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
    763         PyErr_Format(PyExc_TypeError,
    764                      "cannot create weak reference to '%s' object",
    765                      Py_TYPE(ob)->tp_name);
    766         return NULL;
    767     }
    768     list = GET_WEAKREFS_LISTPTR(ob);
    769     get_basic_refs(*list, &ref, &proxy);
    770     if (callback == Py_None)
    771         callback = NULL;
    772     if (callback == NULL)
    773         /* return existing weak reference if it exists */
    774         result = ref;
    775     if (result != NULL)
    776         Py_INCREF(result);
    777     else {
    778         /* Note: new_weakref() can trigger cyclic GC, so the weakref
    779            list on ob can be mutated.  This means that the ref and
    780            proxy pointers we got back earlier may have been collected,
    781            so we need to compute these values again before we use
    782            them. */
    783         result = new_weakref(ob, callback);
    784         if (result != NULL) {
    785             get_basic_refs(*list, &ref, &proxy);
    786             if (callback == NULL) {
    787                 if (ref == NULL)
    788                     insert_head(result, list);
    789                 else {
    790                     /* Someone else added a ref without a callback
    791                        during GC.  Return that one instead of this one
    792                        to avoid violating the invariants of the list
    793                        of weakrefs for ob. */
    794                     Py_DECREF(result);
    795                     Py_INCREF(ref);
    796                     result = ref;
    797                 }
    798             }
    799             else {
    800                 PyWeakReference *prev;
    801 
    802                 prev = (proxy == NULL) ? ref : proxy;
    803                 if (prev == NULL)
    804                     insert_head(result, list);
    805                 else
    806                     insert_after(result, prev);
    807             }
    808         }
    809     }
    810     return (PyObject *) result;
    811 }
    812 
    813 
    814 PyObject *
    815 PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
    816 {
    817     PyWeakReference *result = NULL;
    818     PyWeakReference **list;
    819     PyWeakReference *ref, *proxy;
    820 
    821     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
    822         PyErr_Format(PyExc_TypeError,
    823                      "cannot create weak reference to '%s' object",
    824                      Py_TYPE(ob)->tp_name);
    825         return NULL;
    826     }
    827     list = GET_WEAKREFS_LISTPTR(ob);
    828     get_basic_refs(*list, &ref, &proxy);
    829     if (callback == Py_None)
    830         callback = NULL;
    831     if (callback == NULL)
    832         /* attempt to return an existing weak reference if it exists */
    833         result = proxy;
    834     if (result != NULL)
    835         Py_INCREF(result);
    836     else {
    837         /* Note: new_weakref() can trigger cyclic GC, so the weakref
    838            list on ob can be mutated.  This means that the ref and
    839            proxy pointers we got back earlier may have been collected,
    840            so we need to compute these values again before we use
    841            them. */
    842         result = new_weakref(ob, callback);
    843         if (result != NULL) {
    844             PyWeakReference *prev;
    845 
    846             if (PyCallable_Check(ob))
    847                 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
    848             else
    849                 Py_TYPE(result) = &_PyWeakref_ProxyType;
    850             get_basic_refs(*list, &ref, &proxy);
    851             if (callback == NULL) {
    852                 if (proxy != NULL) {
    853                     /* Someone else added a proxy without a callback
    854                        during GC.  Return that one instead of this one
    855                        to avoid violating the invariants of the list
    856                        of weakrefs for ob. */
    857                     Py_DECREF(result);
    858                     Py_INCREF(result = proxy);
    859                     goto skip_insert;
    860                 }
    861                 prev = ref;
    862             }
    863             else
    864                 prev = (proxy == NULL) ? ref : proxy;
    865 
    866             if (prev == NULL)
    867                 insert_head(result, list);
    868             else
    869                 insert_after(result, prev);
    870         skip_insert:
    871             ;
    872         }
    873     }
    874     return (PyObject *) result;
    875 }
    876 
    877 
    878 PyObject *
    879 PyWeakref_GetObject(PyObject *ref)
    880 {
    881     if (ref == NULL || !PyWeakref_Check(ref)) {
    882         PyErr_BadInternalCall();
    883         return NULL;
    884     }
    885     return PyWeakref_GET_OBJECT(ref);
    886 }
    887 
    888 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
    889  * handle_weakrefs().
    890  */
    891 static void
    892 handle_callback(PyWeakReference *ref, PyObject *callback)
    893 {
    894     PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
    895 
    896     if (cbresult == NULL)
    897         PyErr_WriteUnraisable(callback);
    898     else
    899         Py_DECREF(cbresult);
    900 }
    901 
    902 /* This function is called by the tp_dealloc handler to clear weak references.
    903  *
    904  * This iterates through the weak references for 'object' and calls callbacks
    905  * for those references which have one.  It returns when all callbacks have
    906  * been attempted.
    907  */
    908 void
    909 PyObject_ClearWeakRefs(PyObject *object)
    910 {
    911     PyWeakReference **list;
    912 
    913     if (object == NULL
    914         || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
    915         || object->ob_refcnt != 0) {
    916         PyErr_BadInternalCall();
    917         return;
    918     }
    919     list = GET_WEAKREFS_LISTPTR(object);
    920     /* Remove the callback-less basic and proxy references */
    921     if (*list != NULL && (*list)->wr_callback == NULL) {
    922         clear_weakref(*list);
    923         if (*list != NULL && (*list)->wr_callback == NULL)
    924             clear_weakref(*list);
    925     }
    926     if (*list != NULL) {
    927         PyWeakReference *current = *list;
    928         Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
    929         PyObject *err_type, *err_value, *err_tb;
    930 
    931         PyErr_Fetch(&err_type, &err_value, &err_tb);
    932         if (count == 1) {
    933             PyObject *callback = current->wr_callback;
    934 
    935             current->wr_callback = NULL;
    936             clear_weakref(current);
    937             if (callback != NULL) {
    938                 if (current->ob_refcnt > 0)
    939                     handle_callback(current, callback);
    940                 Py_DECREF(callback);
    941             }
    942         }
    943         else {
    944             PyObject *tuple;
    945             Py_ssize_t i = 0;
    946 
    947             tuple = PyTuple_New(count * 2);
    948             if (tuple == NULL) {
    949                 _PyErr_ReplaceException(err_type, err_value, err_tb);
    950                 return;
    951             }
    952 
    953             for (i = 0; i < count; ++i) {
    954                 PyWeakReference *next = current->wr_next;
    955 
    956                 if (current->ob_refcnt > 0)
    957                 {
    958                     Py_INCREF(current);
    959                     PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
    960                     PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
    961                 }
    962                 else {
    963                     Py_DECREF(current->wr_callback);
    964                 }
    965                 current->wr_callback = NULL;
    966                 clear_weakref(current);
    967                 current = next;
    968             }
    969             for (i = 0; i < count; ++i) {
    970                 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
    971 
    972                 /* The tuple may have slots left to NULL */
    973                 if (callback != NULL) {
    974                     PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
    975                     handle_callback((PyWeakReference *)item, callback);
    976                 }
    977             }
    978             Py_DECREF(tuple);
    979         }
    980         assert(!PyErr_Occurred());
    981         PyErr_Restore(err_type, err_value, err_tb);
    982     }
    983 }
    984