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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}