summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2003-03-24 23:49:49 (GMT)
committerGuido van Rossum <guido@python.org>2003-03-24 23:49:49 (GMT)
commit8d24ee97dfa0e300f8b775faee7a53ad2a02ecac (patch)
tree006c0660588142f1ee7a606d64381618618b9810 /Objects
parentb39903b0a0f1660714939002170d26f020ffc85a (diff)
downloadcpython-8d24ee97dfa0e300f8b775faee7a53ad2a02ecac.zip
cpython-8d24ee97dfa0e300f8b775faee7a53ad2a02ecac.tar.gz
cpython-8d24ee97dfa0e300f8b775faee7a53ad2a02ecac.tar.bz2
Refactoring: rename update_these_slots() into update_subclasses() and
generalize to take a callback function and a void * data argument. This might come in handy later... :-)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c115
1 files changed, 68 insertions, 47 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 4acee5a..4a13928 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -130,6 +130,12 @@ static int add_subclass(PyTypeObject*, PyTypeObject*);
static void remove_subclass(PyTypeObject *, PyTypeObject *);
static void update_all_slots(PyTypeObject *);
+typedef int (*update_callback)(PyTypeObject *, void *);
+static int update_subclasses(PyTypeObject *type, PyObject *name,
+ update_callback callback, void *data);
+static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,
+ update_callback callback, void *data);
+
static int
mro_subclasses(PyTypeObject *type, PyObject* temp)
{
@@ -2031,6 +2037,10 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
type->tp_name);
return -1;
}
+ /* XXX Example of how I expect this to be used...
+ if (update_subclasses(type, name, invalidate_cache, NULL) < 0)
+ return -1;
+ */
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
return -1;
return update_slot(type, name);
@@ -4993,7 +5003,7 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
return res;
}
-/* Common code for update_these_slots() and fixup_slot_dispatchers(). This
+/* Common code for update_slots_callback() and fixup_slot_dispatchers(). This
does some incredibly complex thinking and then sticks something into the
slot. (It sees if the adjacent slotdefs for the same slot have conflicting
interests, and then stores a generic wrapper or a specific function into
@@ -5068,51 +5078,15 @@ update_one_slot(PyTypeObject *type, slotdef *p)
return p;
}
-static int recurse_down_subclasses(PyTypeObject *type, slotdef **pp,
- PyObject *name);
-
-/* In the type, update the slots whose slotdefs are gathered in the pp0 array,
- and then do the same for all this type's subtypes. */
+/* In the type, update the slots whose slotdefs are gathered in the pp array.
+ This is a callback for update_subclasses(). */
static int
-update_these_slots(PyTypeObject *type, slotdef **pp0, PyObject *name)
+update_slots_callback(PyTypeObject *type, void *data)
{
- slotdef **pp;
+ slotdef **pp = (slotdef **)data;
- for (pp = pp0; *pp; pp++)
+ for (; *pp; pp++)
update_one_slot(type, *pp);
- return recurse_down_subclasses(type, pp0, name);
-}
-
-/* Update the slots whose slotdefs are gathered in the pp array in all (direct
- or indirect) subclasses of type. */
-static int
-recurse_down_subclasses(PyTypeObject *type, slotdef **pp, PyObject *name)
-{
- PyTypeObject *subclass;
- PyObject *ref, *subclasses, *dict;
- int i, n;
-
- subclasses = type->tp_subclasses;
- if (subclasses == NULL)
- return 0;
- assert(PyList_Check(subclasses));
- n = PyList_GET_SIZE(subclasses);
- for (i = 0; i < n; i++) {
- ref = PyList_GET_ITEM(subclasses, i);
- assert(PyWeakref_CheckRef(ref));
- subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
- assert(subclass != NULL);
- if ((PyObject *)subclass == Py_None)
- continue;
- assert(PyType_Check(subclass));
- /* Avoid recursing down into unaffected classes */
- dict = subclass->tp_dict;
- if (dict != NULL && PyDict_Check(dict) &&
- PyDict_GetItem(dict, name) != NULL)
- continue;
- if (update_these_slots(subclass, pp, name) < 0)
- return -1;
- }
return 0;
}
@@ -5175,7 +5149,8 @@ update_slot(PyTypeObject *type, PyObject *name)
}
if (ptrs[0] == NULL)
return 0; /* Not an attribute that affects any slots */
- return update_these_slots(type, ptrs, name);
+ return update_subclasses(type, name,
+ update_slots_callback, (void *)ptrs);
}
/* Store the proper functions in the slot dispatches at class (type)
@@ -5203,6 +5178,51 @@ update_all_slots(PyTypeObject* type)
}
}
+/* recurse_down_subclasses() and update_subclasses() are mutually
+ recursive functions to call a callback for all subclasses,
+ but refraining from recursing into subclasses that define 'name'. */
+
+static int
+update_subclasses(PyTypeObject *type, PyObject *name,
+ update_callback callback, void *data)
+{
+ if (callback(type, data) < 0)
+ return -1;
+ return recurse_down_subclasses(type, name, callback, data);
+}
+
+static int
+recurse_down_subclasses(PyTypeObject *type, PyObject *name,
+ update_callback callback, void *data)
+{
+ PyTypeObject *subclass;
+ PyObject *ref, *subclasses, *dict;
+ int i, n;
+
+ subclasses = type->tp_subclasses;
+ if (subclasses == NULL)
+ return 0;
+ assert(PyList_Check(subclasses));
+ n = PyList_GET_SIZE(subclasses);
+ for (i = 0; i < n; i++) {
+ ref = PyList_GET_ITEM(subclasses, i);
+ assert(PyWeakref_CheckRef(ref));
+ subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
+ assert(subclass != NULL);
+ if ((PyObject *)subclass == Py_None)
+ continue;
+ assert(PyType_Check(subclass));
+ /* Avoid recursing down into unaffected classes */
+ dict = subclass->tp_dict;
+ if (dict != NULL && PyDict_Check(dict) &&
+ PyDict_GetItem(dict, name) != NULL)
+ continue;
+ if (update_subclasses(subclass, name, callback, data) < 0)
+ return -1;
+ }
+ return 0;
+}
+
/* This function is called by PyType_Ready() to populate the type's
dictionary with method descriptors for function slots. For each
function slot (like tp_repr) that's defined in the type, one or more
@@ -5216,10 +5236,11 @@ update_all_slots(PyTypeObject* type)
In the latter case, the first slotdef entry encoutered wins. Since
slotdef entries are sorted by the offset of the slot in the
PyHeapTypeObject, this gives us some control over disambiguating
- between competing slots: the members of PyHeapTypeObject are listed from most
- general to least general, so the most general slot is preferred. In
- particular, because as_mapping comes before as_sequence, for a type
- that defines both mp_subscript and sq_item, mp_subscript wins.
+ between competing slots: the members of PyHeapTypeObject are listed
+ from most general to least general, so the most general slot is
+ preferred. In particular, because as_mapping comes before as_sequence,
+ for a type that defines both mp_subscript and sq_item, mp_subscript
+ wins.
This only adds new descriptors and doesn't overwrite entries in
tp_dict that were previously defined. The descriptors contain a