Commit ec72bdca authored by Tim Peters's avatar Tim Peters

BTree_length_or_nonzero(): Sped this. In the nonzero case,

a BTree is empty if and only if its firstbucket pointer is
NULL, so there's no need to keep checking nonzero inside the
loop.  Also, the pointers here are all local, so there's no
need to incref and decref them -- the apparent necessity was
just an artifact of using the bucket assignment macros.  So
stopped using those macros, and the need for incref/decref
operations went away too.

PyVar_AssignB(), ASSIGNB(), ASSIGNBC():  Turned out these
are no longer used anywhere anymore, so removed them.

PER_UNUSE():  New macro to capture the endlessly repeated
PER_ALLOW_DEACTIVATION + PER_ACCESSED pair.  As the comment
says, so sue me <wink>.

Bucket_deleteNextBucket():  Documented & simplified.
parent a7a60ba9
......@@ -42,6 +42,17 @@
#define PER_CHANGED(O) 0
#endif
/* So sue me. This pair gets used all over the place, so much so that it
* interferes with understanding non-persistence parts of algorithms.
* PER_UNUSE can be used after a successul PER_USE or PER_USE_OR_RETURN.
* It allows the object to become ghostified, and tells the persistence
* machinery that the object's fields were used recently.
*/
#define PER_UNUSE(OBJ) do { \
PER_ALLOW_DEACTIVATION(OBJ); \
PER_ACCESSED(OBJ); \
} while (0)
static PyObject *sort_str, *reverse_str, *items_str, *__setstate___str;
static PyObject *ConflictError = NULL;
......@@ -112,10 +123,6 @@ typedef struct Bucket_s {
#define BUCKET(O) ((Bucket*)(O))
static void PyVar_AssignB(Bucket **v, Bucket *e) { Py_XDECREF(*v); *v=e;}
#define ASSIGNB(V,E) PyVar_AssignB(&(V),(E))
#define ASSIGNBC(V,E) (Py_INCREF((E)), PyVar_AssignB(&(V),(E)))
/* A BTree is complicated. See Maintainer.txt.
*/
......@@ -369,7 +376,7 @@ static char BTree_module_documentation[] =
"\n"
MASTER_ID
BTREEITEMSTEMPLATE_C
"$Id: BTreeModuleTemplate.c,v 1.35 2002/06/18 15:58:22 tim_one Exp $\n"
"$Id: BTreeModuleTemplate.c,v 1.36 2002/06/20 02:40:01 tim_one Exp $\n"
BTREETEMPLATE_C
BUCKETTEMPLATE_C
KEYMACROS_H
......
......@@ -12,7 +12,7 @@
****************************************************************************/
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.64 2002/06/19 23:44:20 tim_one Exp $\n"
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.65 2002/06/20 02:40:01 tim_one Exp $\n"
/* Sanity-check a BTree. This is a private helper for BTree_check. Return:
* -1 Error. If it's an internal inconsistency in the BTree,
......@@ -1608,38 +1608,43 @@ BTree_dealloc(BTree *self)
PyObject_Del(self);
}
/*
* Return the number of elements in a BTree. nonzero is a Boolean, and
* when true requests just a non-empty/empty result. Testing for emptiness
* is efficient (constant-time). Getting the true length takes time
* proportional to the number of leaves (buckets).
*
* Return:
* When nonzero true:
* -1 error
* 0 empty
* 1 not empty
* When nonzero false (possibly expensive!):
* -1 error
* >= 0 number of elements.
*/
static int
BTree_length_or_nonzero(BTree *self, int nonzero)
{
int c=0;
Bucket *b, *n;
int result;
Bucket *b;
Bucket *next;
PER_USE_OR_RETURN(self, -1);
b = self->firstbucket;
Py_XINCREF(b);
PER_ALLOW_DEACTIVATION(self);
PER_ACCESSED(self);
PER_USE_OR_RETURN(self, -1);
b = self->firstbucket;
PER_UNUSE(self);
if (nonzero)
return b != NULL;
while (b != NULL)
{
PER_USE_OR_RETURN(b, -1);
c += b->len;
if (nonzero && c)
{
/* Short-circuit if all we care about is nonempty */
PER_ALLOW_DEACTIVATION(b);
PER_ACCESSED(b);
Py_DECREF(b);
return 1;
}
n = b->next;
Py_XINCREF(n);
PER_ALLOW_DEACTIVATION(b);
PER_ACCESSED(b);
ASSIGNB(b, n);
result = 0;
while (b) {
PER_USE_OR_RETURN(b, -1);
result += b->len;
next = b->next;
PER_UNUSE(b);
b = next;
}
return c;
return result;
}
static int
......
......@@ -12,7 +12,7 @@
****************************************************************************/
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.43 2002/06/18 15:58:22 tim_one Exp $\n"
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.44 2002/06/20 02:40:01 tim_one Exp $\n"
/* Use BUCKET_SEARCH to find the index at which a key belongs.
* INDEX An int lvalue to hold the index i such that KEY belongs at
......@@ -474,26 +474,41 @@ Bucket_nextBucket(Bucket *self, Bucket **r)
return 0;
}
/* Set self->next to self->next->next, i.e. unlink self's successor from
* the chain.
*
* Return:
* -1 error
* 0 OK
*/
static int
Bucket_deleteNextBucket(Bucket *self)
{
int result = -1; /* until proven innocent */
int result = -1; /* until proven innocent */
Bucket *successor;
PER_USE_OR_RETURN(self, -1);
if (self->next)
{
Bucket *n;
if (Bucket_nextBucket(self->next, &n) < 0) goto Done;
ASSIGNB(self->next, n);
if (PER_CHANGED(self) < 0)
goto Done;
PER_USE_OR_RETURN(self, -1);
successor = self->next;
if (successor) {
Bucket *next;
/* Before: self -> successor -> next
* After: self --------------> next
*/
UNLESS (PER_USE(successor)) goto Done;
next = successor->next;
PER_UNUSE(successor);
Py_XINCREF(next); /* it may be NULL, of course */
self->next = next;
Py_DECREF(successor);
if (PER_CHANGED(self) < 0)
goto Done;
}
result = 0;
result = 0;
Done:
PER_ALLOW_DEACTIVATION(self);
PER_ACCESSED(self);
return result;
PER_UNUSE(self);
return result;
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment