[Python-checkins] cpython: Miscellaneous refactorings

raymond.hettinger python-checkins at python.org
Sun Jan 24 12:12:14 EST 2016


https://hg.python.org/cpython/rev/3471a3515827
changeset:   100059:3471a3515827
user:        Raymond Hettinger <python at rcn.com>
date:        Sun Jan 24 09:12:06 2016 -0800
summary:
  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.

files:
  Modules/_collectionsmodule.c |  123 ++++++++++------------
  1 files changed, 58 insertions(+), 65 deletions(-)


diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -81,7 +81,7 @@
     Py_ssize_t leftindex;       /* 0 <= leftindex < BLOCKLEN */
     Py_ssize_t rightindex;      /* 0 <= rightindex < BLOCKLEN */
     size_t state;               /* incremented whenever the indices move */
-    Py_ssize_t maxlen;
+    Py_ssize_t maxlen;          /* maxlen is -1 for unbounded deques */
     PyObject *weakreflist;
 } dequeobject;
 
@@ -264,13 +264,13 @@
 
 #define NEEDS_TRIM(deque, maxlen) ((size_t)(maxlen) < (size_t)(Py_SIZE(deque)))
 
-static PyObject *
-deque_append(dequeobject *deque, PyObject *item)
+int
+deque_append_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
 {
     if (deque->rightindex == BLOCKLEN - 1) {
         block *b = newblock();
         if (b == NULL)
-            return NULL;
+            return -1;
         b->leftlink = deque->rightblock;
         CHECK_END(deque->rightblock->rightlink);
         deque->rightblock->rightlink = b;
@@ -279,27 +279,35 @@
         deque->rightindex = -1;
     }
     Py_SIZE(deque)++;
-    Py_INCREF(item);
     deque->rightindex++;
     deque->rightblock->data[deque->rightindex] = item;
-    if (NEEDS_TRIM(deque, deque->maxlen)) {
+    if (NEEDS_TRIM(deque, maxlen)) {
         PyObject *olditem = deque_popleft(deque, NULL);
         Py_DECREF(olditem);
     } else {
         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;
 }
 
 PyDoc_STRVAR(append_doc, "Add an element to the right side of the deque.");
 
-static PyObject *
-deque_appendleft(dequeobject *deque, PyObject *item)
+int
+deque_appendleft_internal(dequeobject *deque, PyObject *item, Py_ssize_t maxlen)
 {
     if (deque->leftindex == 0) {
         block *b = newblock();
         if (b == NULL)
-            return NULL;
+            return -1;
         b->rightlink = deque->leftblock;
         CHECK_END(deque->leftblock->leftlink);
         deque->leftblock->leftlink = b;
@@ -308,7 +316,6 @@
         deque->leftindex = BLOCKLEN;
     }
     Py_SIZE(deque)++;
-    Py_INCREF(item);
     deque->leftindex--;
     deque->leftblock->data[deque->leftindex] = item;
     if (NEEDS_TRIM(deque, deque->maxlen)) {
@@ -317,6 +324,15 @@
     } else {
         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;
 }
 
@@ -387,28 +403,10 @@
 
     iternext = *Py_TYPE(it)->tp_iternext;
     while ((item = iternext(it)) != NULL) {
-        if (deque->rightindex == BLOCKLEN - 1) {
-            block *b = newblock();
-            if (b == NULL) {
-                Py_DECREF(item);
-                Py_DECREF(it);
-                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++;
+        if (deque_append_internal(deque, item, maxlen) < 0) {
+            Py_DECREF(item);
+            Py_DECREF(it);
+            return NULL;
         }
     }
     return finalize_iterator(it);
@@ -452,28 +450,10 @@
 
     iternext = *Py_TYPE(it)->tp_iternext;
     while ((item = iternext(it)) != NULL) {
-        if (deque->leftindex == 0) {
-            block *b = newblock();
-            if (b == NULL) {
-                Py_DECREF(item);
-                Py_DECREF(it);
-                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++;
+        if (deque_appendleft_internal(deque, item, maxlen) < 0) {
+            Py_DECREF(item);
+            Py_DECREF(it);
+            return NULL;
         }
     }
     return finalize_iterator(it);
@@ -565,8 +545,9 @@
     block *prevblock;
     block *leftblock;
     Py_ssize_t leftindex;
-    Py_ssize_t n;
+    Py_ssize_t n, m;
     PyObject *item;
+    PyObject **itemptr, **limit;
 
     if (Py_SIZE(deque) == 0)
         return;
@@ -608,17 +589,25 @@
     /* Now the old size, leftblock, and leftindex are disconnected from
        the empty deque and we can use them to decref the pointers.
     */
-    while (n--) {
-        item = leftblock->data[leftindex];
-        Py_DECREF(item);
-        leftindex++;
-        if (leftindex == BLOCKLEN && n) {
+    itemptr = &leftblock->data[leftindex];
+    m = (BLOCKLEN - leftindex > n) ? n : BLOCKLEN - leftindex;
+    limit = &leftblock->data[leftindex + m];
+    n -= m;
+    while (1) {
+        if (itemptr == limit) {
+            if (n == 0)
+                break;
             CHECK_NOT_END(leftblock->rightlink);
             prevblock = leftblock;
             leftblock = leftblock->rightlink;
-            leftindex = 0;
+            itemptr = leftblock->data;
+            m = (n > BLOCKLEN) ? BLOCKLEN : n;
+            limit = &leftblock->data[m];
+            n -= m;
             freeblock(prevblock);
         }
+        item = *(itemptr++);
+        Py_DECREF(item);
     }
     CHECK_END(leftblock->rightlink);
     freeblock(leftblock);
@@ -1185,14 +1174,16 @@
         i = (Py_ssize_t)((size_t) i % BLOCKLEN);
         if (index < (Py_SIZE(deque) >> 1)) {
             b = deque->leftblock;
-            while (n--)
+            n++;
+            while (--n)
                 b = b->rightlink;
         } else {
             n = (Py_ssize_t)(
                     ((size_t)(deque->leftindex + Py_SIZE(deque) - 1))
                     / BLOCKLEN - n);
             b = deque->rightblock;
-            while (n--)
+            n++;
+            while (--n)
                 b = b->leftlink;
         }
     }
@@ -1235,14 +1226,16 @@
     i = (Py_ssize_t)((size_t) i % BLOCKLEN);
     if (index <= halflen) {
         b = deque->leftblock;
-        while (n--)
+        n++;
+        while (--n)
             b = b->rightlink;
     } else {
         n = (Py_ssize_t)(
                 ((size_t)(deque->leftindex + Py_SIZE(deque) - 1))
                 / BLOCKLEN - n);
         b = deque->rightblock;
-        while (n--)
+        n++;
+        while (--n)
             b = b->leftlink;
     }
     Py_INCREF(v);

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list