PyObject * PyWeakref_NewRef(PyObject *ob, PyObject *callback) { PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->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; }
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(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->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; }
PyObject * PyWeakref_NewProxy(PyObject *ob, PyObject *callback) { PyWeakReference *result = NULL; PyWeakReference **list; PyWeakReference *ref, *proxy; if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) { PyErr_Format(PyExc_TypeError, "cannot create weak reference to '%s' object", ob->ob_type->tp_name); return NULL; } list = GET_WEAKREFS_LISTPTR(ob); get_basic_refs(*list, &ref, &proxy); if (callback == NULL) /* attempt to return an existing weak reference if it exists */ result = proxy; if (result != NULL) Py_XINCREF(result); else { result = new_weakref(ob, callback); if (result != NULL) { PyWeakReference *prev; if (PyCallable_Check(ob)) result->ob_type = &_PyWeakref_CallableProxyType; else result->ob_type = &_PyWeakref_ProxyType; if (callback == NULL) prev = ref; else 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. */ if (PyCallable_Check(ob)) result = new_weakref(ob, callback, &_PyWeakref_CallableProxyType); else result = new_weakref(ob, callback, &_PyWeakref_ProxyType); if (result != NULL) { PyWeakReference *prev; //JyNI-note: These lines mess up JyNI-initialization. //In new_weakref _PyObject_GC_New(&_PyWeakref_RefType) is //called, which caches the tme for _PyWeakref_RefType in //jy->jy. Now the type is altered afterwards leading to //a wrong tme. Shall we fix it here, or implement a //lookup in unconsistent case? //(Better fix it here) // 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; }