weakrefobject.c 29.3 KB
Newer Older
1 2 3 4 5 6 7 8
#include "Python.h"
#include "structmember.h"


#define GET_WEAKREFS_LISTPTR(o) \
        ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))


9
Py_ssize_t
10 11
_PyWeakref_GetWeakrefCount(PyWeakReference *head)
{
12
    Py_ssize_t count = 0;
13 14 15 16 17 18 19 20 21

    while (head != NULL) {
        ++count;
        head = head->wr_next;
    }
    return count;
}


22 23 24 25 26 27 28 29 30
static void
init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
{
    self->hash = -1;
    self->wr_object = ob;
    Py_XINCREF(callback);
    self->wr_callback = callback;
}

31
static PyWeakReference *
32
new_weakref(PyObject *ob, PyObject *callback)
33 34 35
{
    PyWeakReference *result;

36 37
    result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
    if (result) {
38
        init_weakref(result, ob, callback);
39 40
        PyObject_GC_Track(result);
    }
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
    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)
60 61 62
            /* 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. */
63 64 65 66 67 68 69 70
            *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;
71 72 73 74
    }
    if (callback != NULL) {
        Py_DECREF(callback);
        self->wr_callback = NULL;
75 76 77
    }
}

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
/* 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;
}
102 103

static void
104
weakref_dealloc(PyObject *self)
105
{
106 107
    PyObject_GC_UnTrack(self);
    clear_weakref((PyWeakReference *) self);
108
    Py_TYPE(self)->tp_free(self);
109 110 111 112 113 114
}


static int
gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
{
115
    Py_VISIT(self->wr_callback);
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    return 0;
}


static int
gc_clear(PyWeakReference *self)
{
    clear_weakref(self);
    return 0;
}


static PyObject *
weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
{
131
    static char *kwlist[] = {NULL};
132

133
    if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
134 135 136 137 138 139 140 141
        PyObject *object = PyWeakref_GET_OBJECT(self);
        Py_INCREF(object);
        return (object);
    }
    return NULL;
}


142
static Py_hash_t
143 144 145 146 147 148 149 150 151 152 153
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;
}
154

155 156 157 158

static PyObject *
weakref_repr(PyWeakReference *self)
{
159 160 161 162 163 164 165 166 167 168 169 170 171 172
    PyObject *name, *repr;

    if (PyWeakref_GET_OBJECT(self) == Py_None)
        return PyUnicode_FromFormat("<weakref at %p; dead>", self);

    name = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self), "__name__");
    if (name == NULL || !PyUnicode_Check(name)) {
        if (name == NULL)
            PyErr_Clear();
        repr = PyUnicode_FromFormat(
            "<weakref at %p; to '%s' at %p>",
            self,
            Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
            PyWeakref_GET_OBJECT(self));
173 174
    }
    else {
175 176 177 178 179 180
        repr = PyUnicode_FromFormat(
            "<weakref at %p; to '%s' at %p (%U)>",
            self,
            Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
            PyWeakref_GET_OBJECT(self),
            name);
181
    }
182 183
    Py_XDECREF(name);
    return repr;
184 185 186 187 188 189 190 191 192
}

/* 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)
{
193
    if ((op != Py_EQ && op != Py_NE) ||
194 195
        !PyWeakref_Check(self) ||
        !PyWeakref_Check(other)) {
196 197 198 199 200 201 202 203 204 205 206 207 208
        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);
}

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
/* 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;

282
        if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
283 284
            PyErr_Format(PyExc_TypeError,
                         "cannot create weak reference to '%s' object",
285
                         Py_TYPE(ob)->tp_name);
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
            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
334
        return -1;
335 336
}

337 338 339

PyTypeObject
_PyWeakref_RefType = {
340
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
341 342 343
    "weakref",
    sizeof(PyWeakReference),
    0,
344
    weakref_dealloc,            /*tp_dealloc*/
345
    0,                          /*tp_print*/
346 347
    0,                          /*tp_getattr*/
    0,                          /*tp_setattr*/
348
    0,                          /*tp_reserved*/
349 350 351 352
    (reprfunc)weakref_repr,     /*tp_repr*/
    0,                          /*tp_as_number*/
    0,                          /*tp_as_sequence*/
    0,                          /*tp_as_mapping*/
353
    (hashfunc)weakref_hash,     /*tp_hash*/
354 355 356 357 358
    (ternaryfunc)weakref_call,  /*tp_call*/
    0,                          /*tp_str*/
    0,                          /*tp_getattro*/
    0,                          /*tp_setattro*/
    0,                          /*tp_as_buffer*/
359
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
360
        | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
361 362 363
    0,                          /*tp_doc*/
    (traverseproc)gc_traverse,  /*tp_traverse*/
    (inquiry)gc_clear,          /*tp_clear*/
364
    (richcmpfunc)weakref_richcompare,   /*tp_richcompare*/
365 366 367 368 369 370 371 372 373 374 375
    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*/
376
    weakref___init__,           /*tp_init*/
377 378 379
    PyType_GenericAlloc,        /*tp_alloc*/
    weakref___new__,            /*tp_new*/
    PyObject_GC_Del,            /*tp_free*/
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
};


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;
}


395 396 397 398 399 400 401 402 403 404 405
/* 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); \
        }

406 407 408 409 410 411 412
#define UNWRAP_I(o) \
        if (PyWeakref_CheckProxy(o)) { \
            if (!proxy_checkref((PyWeakReference *)o)) \
                return -1; \
            o = PyWeakref_GET_OBJECT(o); \
        }

413 414
#define WRAP_UNARY(method, generic) \
    static PyObject * \
415 416 417
    method(PyObject *proxy) { \
        UNWRAP(proxy); \
        return generic(proxy); \
418 419 420 421
    }

#define WRAP_BINARY(method, generic) \
    static PyObject * \
422 423 424 425
    method(PyObject *x, PyObject *y) { \
        UNWRAP(x); \
        UNWRAP(y); \
        return generic(x, y); \
426 427
    }

428 429
/* Note that the third arg needs to be checked for NULL since the tp_call
 * slot can receive NULL for this arg.
430
 */
431 432
#define WRAP_TERNARY(method, generic) \
    static PyObject * \
433 434
    method(PyObject *proxy, PyObject *v, PyObject *w) { \
        UNWRAP(proxy); \
435
        UNWRAP(v); \
436 437 438
        if (w != NULL) \
            UNWRAP(w); \
        return generic(proxy, v, w); \
439 440
    }

441 442 443
#define WRAP_METHOD(method, special) \
    static PyObject * \
    method(PyObject *proxy) { \
444 445 446
            UNWRAP(proxy); \
                return PyObject_CallMethod(proxy, special, ""); \
        }
447

448 449 450 451 452 453 454 455 456 457

/* 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)
{
458 459 460 461 462
    return PyUnicode_FromFormat(
        "<weakproxy at %p to %s at %p>",
        proxy,
        Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
        PyWeakref_GET_OBJECT(proxy));
463 464 465 466 467 468 469 470 471 472 473
}


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);
}

474 475
static PyObject *
proxy_richcompare(PyObject *proxy, PyObject *v, int op)
476
{
477 478 479
    UNWRAP(proxy);
    UNWRAP(v);
    return PyObject_RichCompare(proxy, v, op);
480 481 482 483 484 485
}

/* number slots */
WRAP_BINARY(proxy_add, PyNumber_Add)
WRAP_BINARY(proxy_sub, PyNumber_Subtract)
WRAP_BINARY(proxy_mul, PyNumber_Multiply)
Georg Brandl's avatar
Georg Brandl committed
486 487
WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
488 489 490 491 492 493 494 495 496 497 498 499
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)
500
WRAP_UNARY(proxy_int, PyNumber_Long)
501 502 503 504
WRAP_UNARY(proxy_float, PyNumber_Float)
WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandl's avatar
Georg Brandl committed
505 506
WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
507 508 509 510 511 512 513
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)
Georg Brandl's avatar
Georg Brandl committed
514
WRAP_UNARY(proxy_index, PyNumber_Index)
515

516
static int
517
proxy_bool(PyWeakReference *proxy)
518 519 520
{
    PyObject *o = PyWeakref_GET_OBJECT(proxy);
    if (!proxy_checkref(proxy))
521
        return -1;
522
    return PyObject_IsTrue(o);
523 524
}

525 526 527 528 529 530 531 532 533
static void
proxy_dealloc(PyWeakReference *self)
{
    if (self->wr_callback != NULL)
        PyObject_GC_UnTrack((PyObject *)self);
    clear_weakref(self);
    PyObject_GC_Del(self);
}

534 535 536 537 538 539 540 541 542 543 544 545 546
/* sequence slots */

static int
proxy_contains(PyWeakReference *proxy, PyObject *value)
{
    if (!proxy_checkref(proxy))
        return -1;
    return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
}


/* mapping slots */

Martin v. Löwis's avatar
Martin v. Löwis committed
547
static Py_ssize_t
548 549 550 551 552 553 554 555 556 557 558 559 560 561
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;
562 563 564 565 566

    if (value == NULL)
        return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
    else
        return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
567 568
}

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
/* 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));
}

587

588
WRAP_METHOD(proxy_bytes, "__bytes__")
589 590 591


static PyMethodDef proxy_methods[] = {
592 593
        {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
        {NULL, NULL}
594 595 596
};


597
static PyNumberMethods proxy_as_number = {
598 599 600 601 602 603 604 605 606
    proxy_add,              /*nb_add*/
    proxy_sub,              /*nb_subtract*/
    proxy_mul,              /*nb_multiply*/
    proxy_mod,              /*nb_remainder*/
    proxy_divmod,           /*nb_divmod*/
    proxy_pow,              /*nb_power*/
    proxy_neg,              /*nb_negative*/
    proxy_pos,              /*nb_positive*/
    proxy_abs,              /*nb_absolute*/
607
    (inquiry)proxy_bool,    /*nb_bool*/
608 609 610 611 612 613 614
    proxy_invert,           /*nb_invert*/
    proxy_lshift,           /*nb_lshift*/
    proxy_rshift,           /*nb_rshift*/
    proxy_and,              /*nb_and*/
    proxy_xor,              /*nb_xor*/
    proxy_or,               /*nb_or*/
    proxy_int,              /*nb_int*/
615
    0,                      /*nb_reserved*/
616 617 618 619 620 621 622 623 624 625 626
    proxy_float,            /*nb_float*/
    proxy_iadd,             /*nb_inplace_add*/
    proxy_isub,             /*nb_inplace_subtract*/
    proxy_imul,             /*nb_inplace_multiply*/
    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*/
Georg Brandl's avatar
Georg Brandl committed
627 628 629 630 631
    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*/
632 633 634
};

static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis's avatar
Martin v. Löwis committed
635
    (lenfunc)proxy_length,      /*sq_length*/
636 637 638
    0,                          /*sq_concat*/
    0,                          /*sq_repeat*/
    0,                          /*sq_item*/
639
    0,                          /*sq_slice*/
640
    0,                          /*sq_ass_item*/
641
    0,                           /*sq_ass_slice*/
642 643 644 645
    (objobjproc)proxy_contains, /* sq_contains */
};

static PyMappingMethods proxy_as_mapping = {
646 647
    (lenfunc)proxy_length,        /*mp_length*/
    proxy_getitem,                /*mp_subscript*/
648 649 650 651 652 653
    (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
};


PyTypeObject
_PyWeakref_ProxyType = {
654
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
655 656 657 658
    "weakproxy",
    sizeof(PyWeakReference),
    0,
    /* methods */
659
    (destructor)proxy_dealloc,          /* tp_dealloc */
660 661 662 663 664 665 666 667 668 669
    0,                                  /* tp_print */
    0,                                  /* tp_getattr */
    0,                                  /* tp_setattr */
    0,                                  /* tp_reserved */
    (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 */
670 671
    proxy_str,                          /* tp_str */
    proxy_getattr,                      /* tp_getattro */
672
    (setattrofunc)proxy_setattr,        /* tp_setattro */
673
    0,                                  /* tp_as_buffer */
674
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
675 676 677
    0,                                  /* tp_doc */
    (traverseproc)gc_traverse,          /* tp_traverse */
    (inquiry)gc_clear,                  /* tp_clear */
678
    proxy_richcompare,                  /* tp_richcompare */
679 680 681
    0,                                  /* tp_weaklistoffset */
    (getiterfunc)proxy_iter,            /* tp_iter */
    (iternextfunc)proxy_iternext,       /* tp_iternext */
682
        proxy_methods,                      /* tp_methods */
683 684 685 686 687
};


PyTypeObject
_PyWeakref_CallableProxyType = {
688
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
689 690 691 692
    "weakcallableproxy",
    sizeof(PyWeakReference),
    0,
    /* methods */
693
    (destructor)proxy_dealloc,          /* tp_dealloc */
694 695 696 697 698 699 700 701 702 703 704
    0,                                  /* tp_print */
    0,                                  /* tp_getattr */
    0,                                  /* tp_setattr */
    0,                                  /* tp_reserved */
    (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 */
705
    proxy_getattr,                      /* tp_getattro */
706
    (setattrofunc)proxy_setattr,        /* tp_setattro */
707
    0,                                  /* tp_as_buffer */
708
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
709 710 711
    0,                                  /* tp_doc */
    (traverseproc)gc_traverse,          /* tp_traverse */
    (inquiry)gc_clear,                  /* tp_clear */
712
    proxy_richcompare,                  /* tp_richcompare */
713 714 715
    0,                                  /* tp_weaklistoffset */
    (getiterfunc)proxy_iter,            /* tp_iter */
    (iternextfunc)proxy_iternext,       /* tp_iternext */
716 717 718 719 720 721 722 723 724 725 726
};



PyObject *
PyWeakref_NewRef(PyObject *ob, PyObject *callback)
{
    PyWeakReference *result = NULL;
    PyWeakReference **list;
    PyWeakReference *ref, *proxy;

727
    if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
728
        PyErr_Format(PyExc_TypeError,
729
                     "cannot create weak reference to '%s' object",
730
                     Py_TYPE(ob)->tp_name);
731 732 733 734
        return NULL;
    }
    list = GET_WEAKREFS_LISTPTR(ob);
    get_basic_refs(*list, &ref, &proxy);
735 736 737
    if (callback == Py_None)
        callback = NULL;
    if (callback == NULL)
738 739 740
        /* return existing weak reference if it exists */
        result = ref;
    if (result != NULL)
741
        Py_INCREF(result);
742
    else {
743 744 745 746 747
        /* 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. */
748
        result = new_weakref(ob, callback);
749
        if (result != NULL) {
750
            get_basic_refs(*list, &ref, &proxy);
751
            if (callback == NULL) {
752 753 754 755 756 757 758 759 760 761 762
                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;
                }
763 764
            }
            else {
765
                PyWeakReference *prev;
766

767
                prev = (proxy == NULL) ? ref : proxy;
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
                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;

786
    if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
787
        PyErr_Format(PyExc_TypeError,
788
                     "cannot create weak reference to '%s' object",
789
                     Py_TYPE(ob)->tp_name);
790 791 792 793
        return NULL;
    }
    list = GET_WEAKREFS_LISTPTR(ob);
    get_basic_refs(*list, &ref, &proxy);
794 795
    if (callback == Py_None)
        callback = NULL;
796 797 798 799
    if (callback == NULL)
        /* attempt to return an existing weak reference if it exists */
        result = proxy;
    if (result != NULL)
800
        Py_INCREF(result);
801
    else {
802 803 804 805 806
        /* 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. */
807
        result = new_weakref(ob, callback);
808 809 810 811
        if (result != NULL) {
            PyWeakReference *prev;

            if (PyCallable_Check(ob))
812
                Py_TYPE(result) = &_PyWeakref_CallableProxyType;
813
            else
814
                Py_TYPE(result) = &_PyWeakref_ProxyType;
815
            get_basic_refs(*list, &ref, &proxy);
816 817 818 819 820 821 822 823 824 825
            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;
                }
826
                prev = ref;
827
            }
828 829 830 831 832 833 834
            else
                prev = (proxy == NULL) ? ref : proxy;

            if (prev == NULL)
                insert_head(result, list);
            else
                insert_after(result, prev);
835 836
        skip_insert:
            ;
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
        }
    }
    return (PyObject *) result;
}


PyObject *
PyWeakref_GetObject(PyObject *ref)
{
    if (ref == NULL || !PyWeakref_Check(ref)) {
        PyErr_BadInternalCall();
        return NULL;
    }
    return PyWeakref_GET_OBJECT(ref);
}

853 854 855
/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
 * handle_weakrefs().
 */
856 857 858
static void
handle_callback(PyWeakReference *ref, PyObject *callback)
{
859
    PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
860 861 862 863 864 865 866 867

    if (cbresult == NULL)
        PyErr_WriteUnraisable(callback);
    else
        Py_DECREF(cbresult);
}

/* This function is called by the tp_dealloc handler to clear weak references.
868 869 870 871 872 873 874 875 876 877 878
 *
 * 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
879
        || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
880 881 882 883 884 885 886 887 888 889 890 891
        || 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) {
892
        PyWeakReference *current = *list;
Martin v. Löwis's avatar
Martin v. Löwis committed
893
        Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
894 895
        int restore_error = PyErr_Occurred() ? 1 : 0;
        PyObject *err_type, *err_value, *err_tb;
896

897 898
        if (restore_error)
            PyErr_Fetch(&err_type, &err_value, &err_tb);
899 900 901
        if (count == 1) {
            PyObject *callback = current->wr_callback;

902
            current->wr_callback = NULL;
903
            clear_weakref(current);
904
            if (callback != NULL) {
905
                if (((PyObject *)current)->ob_refcnt > 0)
906
                    handle_callback(current, callback);
907 908
                Py_DECREF(callback);
            }
909 910
        }
        else {
911
            PyObject *tuple;
Martin v. Löwis's avatar
Martin v. Löwis committed
912
            Py_ssize_t i = 0;
913

914 915 916 917 918 919
            tuple = PyTuple_New(count * 2);
            if (tuple == NULL) {
                if (restore_error)
                    PyErr_Fetch(&err_type, &err_value, &err_tb);
                return;
            }
920 921 922 923

            for (i = 0; i < count; ++i) {
                PyWeakReference *next = current->wr_next;

924
                if (((PyObject *)current)->ob_refcnt > 0)
925 926 927 928 929 930 931 932
                {
                    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);
                }
933 934 935 936 937 938
                current->wr_callback = NULL;
                clear_weakref(current);
                current = next;
            }
            for (i = 0; i < count; ++i) {
                PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
939

940
                /* The tuple may have slots left to NULL */
941
                if (callback != NULL) {
942 943
                    PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
                    handle_callback((PyWeakReference *)item, callback);
944
                }
945 946 947
            }
            Py_DECREF(tuple);
        }
948 949
        if (restore_error)
            PyErr_Restore(err_type, err_value, err_tb);
950 951
    }
}