📄 weakrefobject.c
字号:
}
/* mapping slots */
static int
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;
return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
}
const static PyNumberMethods proxy_as_number = {
(binaryfunc)proxy_add, /*nb_add*/
(binaryfunc)proxy_sub, /*nb_subtract*/
(binaryfunc)proxy_mul, /*nb_multiply*/
(binaryfunc)proxy_div, /*nb_divide*/
(binaryfunc)proxy_mod, /*nb_remainder*/
(binaryfunc)proxy_divmod, /*nb_divmod*/
(ternaryfunc)proxy_pow, /*nb_power*/
(unaryfunc)proxy_neg, /*nb_negative*/
(unaryfunc)proxy_pos, /*nb_positive*/
(unaryfunc)proxy_abs, /*nb_absolute*/
(inquiry)proxy_nonzero, /*nb_nonzero*/
(unaryfunc)proxy_invert, /*nb_invert*/
(binaryfunc)proxy_lshift, /*nb_lshift*/
(binaryfunc)proxy_rshift, /*nb_rshift*/
(binaryfunc)proxy_and, /*nb_and*/
(binaryfunc)proxy_xor, /*nb_xor*/
(binaryfunc)proxy_or, /*nb_or*/
(coercion)0, /*nb_coerce*/
(unaryfunc)proxy_int, /*nb_int*/
(unaryfunc)proxy_long, /*nb_long*/
(unaryfunc)proxy_float, /*nb_float*/
(unaryfunc)0, /*nb_oct*/
(unaryfunc)0, /*nb_hex*/
(binaryfunc)proxy_iadd, /*nb_inplace_add*/
(binaryfunc)proxy_isub, /*nb_inplace_subtract*/
(binaryfunc)proxy_imul, /*nb_inplace_multiply*/
(binaryfunc)proxy_idiv, /*nb_inplace_divide*/
(binaryfunc)proxy_imod, /*nb_inplace_remainder*/
(ternaryfunc)proxy_ipow, /*nb_inplace_power*/
(binaryfunc)proxy_ilshift, /*nb_inplace_lshift*/
(binaryfunc)proxy_irshift, /*nb_inplace_rshift*/
(binaryfunc)proxy_iand, /*nb_inplace_and*/
(binaryfunc)proxy_ixor, /*nb_inplace_xor*/
(binaryfunc)proxy_ior, /*nb_inplace_or*/
};
const static PySequenceMethods proxy_as_sequence = {
(inquiry)proxy_length, /*sq_length*/
0, /*sq_concat*/
0, /*sq_repeat*/
0, /*sq_item*/
(intintargfunc)proxy_slice, /*sq_slice*/
0, /*sq_ass_item*/
(intintobjargproc)proxy_ass_slice, /*sq_ass_slice*/
(objobjproc)proxy_contains, /* sq_contains */
};
const static PyMappingMethods proxy_as_mapping = {
(inquiry)proxy_length, /*mp_length*/
(binaryfunc)proxy_getitem, /*mp_subscript*/
(objobjargproc)proxy_setitem, /*mp_ass_subscript*/
};
#ifndef SYMBIAN
PyTypeObject
_PyWeakref_ProxyType = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject
_c_PyWeakref_ProxyType = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"weakproxy",
sizeof(PyWeakReference),
0,
/* methods */
(destructor)weakref_dealloc,/*tp_dealloc*/
(printfunc)proxy_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
proxy_compare, /*tp_compare*/
(unaryfunc)proxy_repr, /*tp_repr*/
&proxy_as_number, /*tp_as_number*/
&proxy_as_sequence, /*tp_as_sequence*/
&proxy_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(unaryfunc)proxy_str, /*tp_str*/
(getattrofunc)proxy_getattr,/*tp_getattro*/
(setattrofunc)proxy_setattr,/*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
0, /*tp_doc*/
(traverseproc)gc_traverse, /*tp_traverse*/
(inquiry)gc_clear, /*tp_clear*/
};
#ifndef SYMBIAN
PyTypeObject
_PyWeakref_CallableProxyType = {
PyObject_HEAD_INIT(&PyType_Type)
#else
const PyTypeObject
_c_PyWeakref_CallableProxyType = {
PyObject_HEAD_INIT(NULL)
#endif
0,
"weakcallableproxy",
sizeof(PyWeakReference),
0,
/* methods */
(destructor)weakref_dealloc,/*tp_dealloc*/
(printfunc)proxy_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
proxy_compare, /*tp_compare*/
(unaryfunc)proxy_repr, /*tp_repr*/
&proxy_as_number, /*tp_as_number*/
&proxy_as_sequence, /*tp_as_sequence*/
&proxy_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
(ternaryfunc)proxy_call, /*tp_call*/
(unaryfunc)proxy_str, /*tp_str*/
(getattrofunc)proxy_getattr,/*tp_getattro*/
(setattrofunc)proxy_setattr,/*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
|Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
0, /*tp_doc*/
(traverseproc)gc_traverse, /*tp_traverse*/
(inquiry)gc_clear, /*tp_clear*/
};
/* 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) {
if (head->ob_type == &_PyWeakref_RefType) {
*refp = head;
head = head->wr_next;
}
if (head != NULL && head->wr_callback == NULL) {
*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;
}
DL_EXPORT(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 == NULL || callback == Py_None)
/* return existing weak reference if it exists */
result = ref;
if (result != NULL)
Py_XINCREF(result);
else {
result = new_weakref();
if (result != NULL) {
Py_XINCREF(callback);
result->wr_callback = callback;
result->wr_object = ob;
if (callback == NULL) {
insert_head(result, list);
}
else {
PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
if (prev == NULL)
insert_head(result, list);
else
insert_after(result, prev);
}
PyObject_GC_Track(result);
}
}
return (PyObject *) result;
}
DL_EXPORT(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();
if (result != NULL) {
PyWeakReference *prev;
if (PyCallable_Check(ob))
result->ob_type = &_PyWeakref_CallableProxyType;
else
result->ob_type = &_PyWeakref_ProxyType;
result->wr_object = ob;
Py_XINCREF(callback);
result->wr_callback = callback;
if (callback == NULL)
prev = ref;
else
prev = (proxy == NULL) ? ref : proxy;
if (prev == NULL)
insert_head(result, list);
else
insert_after(result, prev);
PyObject_GC_Track(result);
}
}
return (PyObject *) result;
}
DL_EXPORT(PyObject *)
PyWeakref_GetObject(PyObject *ref)
{
if (ref == NULL || !PyWeakref_Check(ref)) {
PyErr_BadInternalCall();
return NULL;
}
return PyWeakref_GET_OBJECT(ref);
}
static void
handle_callback(PyWeakReference *ref, PyObject *callback)
{
PyObject *cbresult = PyObject_CallFunction(callback, "O", ref);
if (cbresult == NULL)
PyErr_WriteUnraisable(callback);
else
Py_DECREF(cbresult);
}
/* This function is called by the tp_dealloc handler to clear weak references.
*
* This iterates through the weak references for 'object' and calls callbacks
* for those references which have one. It returns when all callbacks have
* been attempted.
*/
DL_EXPORT(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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -