[Zodb-checkins] CVS: Zope/lib/python/BTrees - BTreeTemplate.c:1.58
Tim Peters
tim.one@comcast.net
Mon, 17 Jun 2002 16:02:39 -0400
Update of /cvs-repository/Zope/lib/python/BTrees
In directory cvs.zope.org:/tmp/cvs-serv16987
Modified Files:
BTreeTemplate.c
Log Message:
_BTree_clear(): Made the Zope2 and Zope3 versions as similar as possible.
=== Zope/lib/python/BTrees/BTreeTemplate.c 1.57 => 1.58 ===
** _BTree_clear
**
-** Clears out all of the values in the BTree
+** Clears out all of the values in the BTree (firstbucket, keys, and children);
+** leaving self an empty BTree.
**
** Arguments: self The BTree
**
** Returns: 0 on success
** -1 on failure
-*/
+**
+** Internal: Deallocation order is important. The danger is that a long
+** list of buckets may get freed "at once" via decref'ing the first bucket,
+** in which case a chain of consequenct Py_DECREF calls may blow the stack.
+** Luckily, every bucket has a refcount of at least two, one due to being a
+** BTree node's child, and another either because it's not the first bucket in
+** the chain (so the preceding bucket points to it), or because firstbucket
+** points to it. By clearing in the natural depth-first, left-to-right
+** order, the BTree->bucket child pointers prevent Py_DECREF(bucket->next)
+** calls from freeing bucket->next, and the maximum stack depth is equal
+** to the height of the tree.
+**/
static int
_BTree_clear(BTree *self)
{
- int i, l;
-
- /* The order in which we dealocate, from "top to bottom" is critical
- to prevent memory memory errors when the deallocation stack
- becomes huge when dealocating use linked lists of buckets.
- */
+ const int len = self->len;
- if (self->firstbucket)
- {
- ASSERT(self->firstbucket->ob_refcnt > 0,
- "Invalid firstbucket pointer", -1);
- Py_DECREF(self->firstbucket);
- self->firstbucket=NULL;
+ if (self->firstbucket) {
+ ASSERT(self->firstbucket->ob_refcnt > 1,
+ "Invalid firstbucket pointer", -1);
+ Py_DECREF(self->firstbucket);
+ self->firstbucket = NULL;
}
- for (l=self->len, i=0; i < l; i++)
- {
- if (i)
- {
- DECREF_KEY(self->data[i].key);
- }
- Py_DECREF(self->data[i].child);
- }
- self->len=0;
+ if (self->data) {
+ int i;
+ if (len > 0) { /* 0 is special because key 0 is trash */
+ Py_DECREF(self->data[0].child);
+ }
- if (self->data)
- {
- free(self->data);
- self->data=0;
- self->size=0;
+ for (i = 1; i < len; i++) {
+ DECREF_KEY(self->data[i].key);
+ Py_DECREF(self->data[i].child);
+ }
+ free(self->data);
+ self->data = NULL;
}
- return 0;
+ self->len = self->size = 0;
+ return 0;
}
#ifdef PERSISTENT