Commit d84ec225 authored by Raymond Hettinger's avatar Raymond Hettinger

Miscellaneous refactorings

* Add comment to the maxlen structure entry about the meaning of maxlen == -1
* Factor-out code common to deque_append(left) and deque_extend(left)
* Factor inner-loop in deque_clear() to use only 1 test per loop instead of 2
* Tighten inner-loops for deque_item() and deque_ass_item() so that the
  compiler can combine the decrement and test into a single step.
parent 1aa78938
...@@ -81,7 +81,7 @@ typedef struct { ...@@ -81,7 +81,7 @@ typedef struct {
Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */ Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */
Py_ssize_t rightindex; /* 0 <= rightindex < BLOCKLEN */ Py_ssize_t rightindex; /* 0 <= rightindex < BLOCKLEN */
size_t state; /* incremented whenever the indices move */ size_t state; /* incremented whenever the indices move */
Py_ssize_t maxlen; Py_ssize_t maxlen; /* maxlen is -1 for unbounded deques */
PyObject *weakreflist; PyObject *weakreflist;
} dequeobject; } dequeobject;
...@@ -264,13 +264,13 @@ PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element."); ...@@ -264,13 +264,13 @@ PyDoc_STRVAR(popleft_doc, "Remove and return the leftmost element.");
#define NEEDS_TRIM(deque, maxlen) ((size_t)(maxlen) < (size_t)(Py_SIZE(deque))) #define NEEDS_TRIM(deque, maxlen) ((size_t)(maxlen) < (size_t)(Py_SIZE(deque)))
static PyObject * int
deque_append(dequeobject *deque, PyObject *item) deque_append_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
{ {
if (deque->rightindex == BLOCKLEN - 1) { if (deque->rightindex == BLOCKLEN - 1) {
block *b = newblock(); block *b = newblock();
if (b == NULL) if (b == NULL)
return NULL; return -1;
b->leftlink = deque->rightblock; b->leftlink = deque->rightblock;
CHECK_END(deque->rightblock->rightlink); CHECK_END(deque->rightblock->rightlink);
deque->rightblock->rightlink = b; deque->rightblock->rightlink = b;
...@@ -279,27 +279,35 @@ deque_append(dequeobject *deque, PyObject *item) ...@@ -279,27 +279,35 @@ deque_append(dequeobject *deque, PyObject *item)
deque->rightindex = -1; deque->rightindex = -1;
} }
Py_SIZE(deque)++; Py_SIZE(deque)++;
Py_INCREF(item);
deque->rightindex++; deque->rightindex++;
deque->rightblock->data[deque->rightindex] = item; deque->rightblock->data[deque->rightindex] = item;
if (NEEDS_TRIM(deque, deque->maxlen)) { if (NEEDS_TRIM(deque, maxlen)) {
PyObject *olditem = deque_popleft(deque, NULL); PyObject *olditem = deque_popleft(deque, NULL);
Py_DECREF(olditem); Py_DECREF(olditem);
} else { } else {
deque->state++; deque->state++;
} }
return 0;
}
static PyObject *
deque_append(dequeobject *deque, PyObject *item)
{
Py_INCREF(item);
if (deque_append_internal(deque, item, deque->maxlen) < 0)
return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque."); PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
static PyObject * int
deque_appendleft(dequeobject *deque, PyObject *item) deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
{ {
if (deque->leftindex == 0) { if (deque->leftindex == 0) {
block *b = newblock(); block *b = newblock();
if (b == NULL) if (b == NULL)
return NULL; return -1;
b->rightlink = deque->leftblock; b->rightlink = deque->leftblock;
CHECK_END(deque->leftblock->leftlink); CHECK_END(deque->leftblock->leftlink);
deque->leftblock->leftlink = b; deque->leftblock->leftlink = b;
...@@ -308,7 +316,6 @@ deque_appendleft(dequeobject *deque, PyObject *item) ...@@ -308,7 +316,6 @@ deque_appendleft(dequeobject *deque, PyObject *item)
deque->leftindex = BLOCKLEN; deque->leftindex = BLOCKLEN;
} }
Py_SIZE(deque)++; Py_SIZE(deque)++;
Py_INCREF(item);
deque->leftindex--; deque->leftindex--;
deque->leftblock->data[deque->leftindex] = item; deque->leftblock->data[deque->leftindex] = item;
if (NEEDS_TRIM(deque, deque->maxlen)) { if (NEEDS_TRIM(deque, deque->maxlen)) {
...@@ -317,6 +324,15 @@ deque_appendleft(dequeobject *deque, PyObject *item) ...@@ -317,6 +324,15 @@ deque_appendleft(dequeobject *deque, PyObject *item)
} else { } else {
deque->state++; deque->state++;
} }
return 0;
}
static PyObject *
deque_appendleft(dequeobject *deque, PyObject *item)
{
Py_INCREF(item);
if (deque_appendleft_internal(deque, item, deque->maxlen) < 0)
return NULL;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
...@@ -387,29 +403,11 @@ deque_extend(dequeobject *deque, PyObject *iterable) ...@@ -387,29 +403,11 @@ deque_extend(dequeobject *deque, PyObject *iterable)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
while ((item = iternext(it)) != NULL) { while ((item = iternext(it)) != NULL) {
if (deque->rightindex == BLOCKLEN - 1) { if (deque_append_internal(deque, item, maxlen) < 0) {
block *b = newblock();
if (b == NULL) {
Py_DECREF(item); Py_DECREF(item);
Py_DECREF(it); Py_DECREF(it);
return NULL; return NULL;
} }
b->leftlink = deque->rightblock;
CHECK_END(deque->rightblock->rightlink);
deque->rightblock->rightlink = b;
deque->rightblock = b;
MARK_END(b->rightlink);
deque->rightindex = -1;
}
Py_SIZE(deque)++;
deque->rightindex++;
deque->rightblock->data[deque->rightindex] = item;
if (NEEDS_TRIM(deque, maxlen)) {
PyObject *olditem = deque_popleft(deque, NULL);
Py_DECREF(olditem);
} else {
deque->state++;
}
} }
return finalize_iterator(it); return finalize_iterator(it);
} }
...@@ -452,29 +450,11 @@ deque_extendleft(dequeobject *deque, PyObject *iterable) ...@@ -452,29 +450,11 @@ deque_extendleft(dequeobject *deque, PyObject *iterable)
iternext = *Py_TYPE(it)->tp_iternext; iternext = *Py_TYPE(it)->tp_iternext;
while ((item = iternext(it)) != NULL) { while ((item = iternext(it)) != NULL) {
if (deque->leftindex == 0) { if (deque_appendleft_internal(deque, item, maxlen) < 0) {
block *b = newblock();
if (b == NULL) {
Py_DECREF(item); Py_DECREF(item);
Py_DECREF(it); Py_DECREF(it);
return NULL; return NULL;
} }
b->rightlink = deque->leftblock;
CHECK_END(deque->leftblock->leftlink);
deque->leftblock->leftlink = b;
deque->leftblock = b;
MARK_END(b->leftlink);
deque->leftindex = BLOCKLEN;
}
Py_SIZE(deque)++;
deque->leftindex--;
deque->leftblock->data[deque->leftindex] = item;
if (NEEDS_TRIM(deque, maxlen)) {
PyObject *olditem = deque_pop(deque, NULL);
Py_DECREF(olditem);
} else {
deque->state++;
}
} }
return finalize_iterator(it); return finalize_iterator(it);
} }
...@@ -565,8 +545,9 @@ deque_clear(dequeobject *deque) ...@@ -565,8 +545,9 @@ deque_clear(dequeobject *deque)
block *prevblock; block *prevblock;
block *leftblock; block *leftblock;
Py_ssize_t leftindex; Py_ssize_t leftindex;
Py_ssize_t n; Py_ssize_t n, m;
PyObject *item; PyObject *item;
PyObject **itemptr, **limit;
if (Py_SIZE(deque) == 0) if (Py_SIZE(deque) == 0)
return; return;
...@@ -608,17 +589,25 @@ deque_clear(dequeobject *deque) ...@@ -608,17 +589,25 @@ deque_clear(dequeobject *deque)
/* Now the old size, leftblock, and leftindex are disconnected from /* Now the old size, leftblock, and leftindex are disconnected from
the empty deque and we can use them to decref the pointers. the empty deque and we can use them to decref the pointers.
*/ */
while (n--) { itemptr = &leftblock->data[leftindex];
item = leftblock->data[leftindex]; m = (BLOCKLEN - leftindex > n) ? n : BLOCKLEN - leftindex;
Py_DECREF(item); limit = &leftblock->data[leftindex + m];
leftindex++; n -= m;
if (leftindex == BLOCKLEN && n) { while (1) {
if (itemptr == limit) {
if (n == 0)
break;
CHECK_NOT_END(leftblock->rightlink); CHECK_NOT_END(leftblock->rightlink);
prevblock = leftblock; prevblock = leftblock;
leftblock = leftblock->rightlink; leftblock = leftblock->rightlink;
leftindex = 0; itemptr = leftblock->data;
m = (n > BLOCKLEN) ? BLOCKLEN : n;
limit = &leftblock->data[m];
n -= m;
freeblock(prevblock); freeblock(prevblock);
} }
item = *(itemptr++);
Py_DECREF(item);
} }
CHECK_END(leftblock->rightlink); CHECK_END(leftblock->rightlink);
freeblock(leftblock); freeblock(leftblock);
...@@ -1185,14 +1174,16 @@ deque_item(dequeobject *deque, Py_ssize_t i) ...@@ -1185,14 +1174,16 @@ deque_item(dequeobject *deque, Py_ssize_t i)
i = (Py_ssize_t)((size_t) i % BLOCKLEN); i = (Py_ssize_t)((size_t) i % BLOCKLEN);
if (index < (Py_SIZE(deque) >> 1)) { if (index < (Py_SIZE(deque) >> 1)) {
b = deque->leftblock; b = deque->leftblock;
while (n--) n++;
while (--n)
b = b->rightlink; b = b->rightlink;
} else { } else {
n = (Py_ssize_t)( n = (Py_ssize_t)(
((size_t)(deque->leftindex + Py_SIZE(deque) - 1)) ((size_t)(deque->leftindex + Py_SIZE(deque) - 1))
/ BLOCKLEN - n); / BLOCKLEN - n);
b = deque->rightblock; b = deque->rightblock;
while (n--) n++;
while (--n)
b = b->leftlink; b = b->leftlink;
} }
} }
...@@ -1235,14 +1226,16 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v) ...@@ -1235,14 +1226,16 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
i = (Py_ssize_t)((size_t) i % BLOCKLEN); i = (Py_ssize_t)((size_t) i % BLOCKLEN);
if (index <= halflen) { if (index <= halflen) {
b = deque->leftblock; b = deque->leftblock;
while (n--) n++;
while (--n)
b = b->rightlink; b = b->rightlink;
} else { } else {
n = (Py_ssize_t)( n = (Py_ssize_t)(
((size_t)(deque->leftindex + Py_SIZE(deque) - 1)) ((size_t)(deque->leftindex + Py_SIZE(deque) - 1))
/ BLOCKLEN - n); / BLOCKLEN - n);
b = deque->rightblock; b = deque->rightblock;
while (n--) n++;
while (--n)
b = b->leftlink; b = b->leftlink;
} }
Py_INCREF(v); Py_INCREF(v);
......
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