static PyObject * weakref_getweakrefs(PyObject *self, PyObject *object) { PyObject *result = NULL; if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); result = PyList_New(count); if (result != NULL) { PyWeakReference *current = *list; Py_ssize_t i; for (i = 0; i < count; ++i) { PyList_SET_ITEM(result, i, (PyObject *) current); Py_INCREF(current); current = current->wr_next; } } } else { result = PyList_New(0); } return result; }
/* 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(object->ob_type) || 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; int count = _PyWeakref_GetWeakrefCount(current); int restore_error = PyErr_Occurred() ? 1 : 0; PyObject *err_type, *err_value, *err_tb; 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); handle_callback(current, callback); Py_DECREF(callback); } else { PyObject *tuple = PyTuple_New(count * 2); int i = 0; for (i = 0; i < count; ++i) { PyWeakReference *next = current->wr_next; Py_INCREF(current); PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); current->wr_callback = NULL; clear_weakref(current); current = next; } for (i = 0; i < count; ++i) { PyObject *current = PyTuple_GET_ITEM(tuple, i * 2); PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); handle_callback((PyWeakReference *)current, callback); } Py_DECREF(tuple); } if (restore_error) PyErr_Restore(err_type, err_value, err_tb); } }
/* 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 (self->wr_object != Py_None) { PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object); 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; } }
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 Py_ssize_t _weakref_getweakrefcount_impl(PyObject *module, PyObject *object) /*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/ { PyWeakReference **list; if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) return 0; list = GET_WEAKREFS_LISTPTR(object); return _PyWeakref_GetWeakrefCount(*list); }
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; }
static PyObject * weakref_getweakrefcount(PyObject *self, PyObject *object) { PyObject *result = NULL; if (PyType_SUPPORTS_WEAKREFS(object->ob_type)) { PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); result = PyInt_FromSsize_t(_PyWeakref_GetWeakrefCount(*list)); } else result = PyInt_FromLong(0); return result; }
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; }
/* 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) *list = self->wr_next; self->wr_object = Py_None; self->wr_callback = NULL; 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; Py_XDECREF(callback); } }
/* 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, *err_value, *err_tb; 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) { // Pyston change: // current is a stack reference to a GC allocated object. If it wasn't null when we fetched it from *list, it won't // be collected, and we can trust that it's still valid here. if (true /*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; // Pyston change: // current is a stack reference to a GC allocated object. If it wasn't null when we fetched it from *list, it won't // be collected, and we can trust that it's still valid here. if (true /*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); } }
/* 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); PyObject *err_type, *err_value, *err_tb; 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) { _PyErr_ReplaceException(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); } assert(!PyErr_Occurred()); PyErr_Restore(err_type, err_value, err_tb); } }
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; }