summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2015-09-27 04:31:23 (GMT)
committerRaymond Hettinger <python@rcn.com>2015-09-27 04:31:23 (GMT)
commit8299e9b59ecea5cd7236949bf17392e2fd56aec8 (patch)
treec4b83fc641666a3bf5674934c3b9f163b974531d
parent7c0b70f41910fb70432f32f8ed263a56110a5525 (diff)
downloadcpython-8299e9b59ecea5cd7236949bf17392e2fd56aec8.zip
cpython-8299e9b59ecea5cd7236949bf17392e2fd56aec8.tar.gz
cpython-8299e9b59ecea5cd7236949bf17392e2fd56aec8.tar.bz2
Move the copy and clear functions upwards to eliminate unnecessary forward references.
-rw-r--r--Modules/_collectionsmodule.c230
1 files changed, 113 insertions, 117 deletions
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index 66c2a74..5db7aed 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -522,7 +522,40 @@ deque_inplace_concat(dequeobject *deque, PyObject *other)
return (PyObject *)deque;
}
-static PyObject *deque_copy(PyObject *deque);
+static PyObject *
+deque_copy(PyObject *deque)
+{
+ dequeobject *old_deque = (dequeobject *)deque;
+ if (Py_TYPE(deque) == &deque_type) {
+ dequeobject *new_deque;
+ PyObject *rv;
+
+ new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL);
+ if (new_deque == NULL)
+ return NULL;
+ new_deque->maxlen = old_deque->maxlen;
+ /* Fast path for the deque_repeat() common case where len(deque) == 1 */
+ if (Py_SIZE(deque) == 1 && new_deque->maxlen != 0) {
+ PyObject *item = old_deque->leftblock->data[old_deque->leftindex];
+ rv = deque_append(new_deque, item);
+ } else {
+ rv = deque_extend(new_deque, deque);
+ }
+ if (rv != NULL) {
+ Py_DECREF(rv);
+ return (PyObject *)new_deque;
+ }
+ Py_DECREF(new_deque);
+ return NULL;
+ }
+ if (old_deque->maxlen < 0)
+ return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "O", deque, NULL);
+ else
+ return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
+ deque, old_deque->maxlen, NULL);
+}
+
+PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
static PyObject *
deque_concat(dequeobject *deque, PyObject *other)
@@ -552,7 +585,85 @@ deque_concat(dequeobject *deque, PyObject *other)
return new_deque;
}
-static void deque_clear(dequeobject *deque);
+static void
+deque_clear(dequeobject *deque)
+{
+ block *b;
+ block *prevblock;
+ block *leftblock;
+ Py_ssize_t leftindex;
+ Py_ssize_t n;
+ PyObject *item;
+
+ /* During the process of clearing a deque, decrefs can cause the
+ deque to mutate. To avoid fatal confusion, we have to make the
+ deque empty before clearing the blocks and never refer to
+ anything via deque->ref while clearing. (This is the same
+ technique used for clearing lists, sets, and dicts.)
+
+ Making the deque empty requires allocating a new empty block. In
+ the unlikely event that memory is full, we fall back to an
+ alternate method that doesn't require a new block. Repeating
+ pops in a while-loop is slower, possibly re-entrant (and a clever
+ adversary could cause it to never terminate).
+ */
+
+ b = newblock(0);
+ if (b == NULL) {
+ PyErr_Clear();
+ goto alternate_method;
+ }
+
+ /* Remember the old size, leftblock, and leftindex */
+ leftblock = deque->leftblock;
+ leftindex = deque->leftindex;
+ n = Py_SIZE(deque);
+
+ /* Set the deque to be empty using the newly allocated block */
+ MARK_END(b->leftlink);
+ MARK_END(b->rightlink);
+ Py_SIZE(deque) = 0;
+ deque->leftblock = b;
+ deque->rightblock = b;
+ deque->leftindex = CENTER + 1;
+ deque->rightindex = CENTER;
+ deque->state++;
+
+ /* 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) {
+ CHECK_NOT_END(leftblock->rightlink);
+ prevblock = leftblock;
+ leftblock = leftblock->rightlink;
+ leftindex = 0;
+ freeblock(prevblock);
+ }
+ }
+ CHECK_END(leftblock->rightlink);
+ freeblock(leftblock);
+ return;
+
+ alternate_method:
+ while (Py_SIZE(deque)) {
+ item = deque_pop(deque, NULL);
+ assert (item != NULL);
+ Py_DECREF(item);
+ }
+}
+
+static PyObject *
+deque_clearmethod(dequeobject *deque)
+{
+ deque_clear(deque);
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
static PyObject *
deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
@@ -1058,77 +1169,6 @@ deque_remove(dequeobject *deque, PyObject *value)
PyDoc_STRVAR(remove_doc,
"D.remove(value) -- remove first occurrence of value.");
-static void
-deque_clear(dequeobject *deque)
-{
- block *b;
- block *prevblock;
- block *leftblock;
- Py_ssize_t leftindex;
- Py_ssize_t n;
- PyObject *item;
-
- /* During the process of clearing a deque, decrefs can cause the
- deque to mutate. To avoid fatal confusion, we have to make the
- deque empty before clearing the blocks and never refer to
- anything via deque->ref while clearing. (This is the same
- technique used for clearing lists, sets, and dicts.)
-
- Making the deque empty requires allocating a new empty block. In
- the unlikely event that memory is full, we fall back to an
- alternate method that doesn't require a new block. Repeating
- pops in a while-loop is slower, possibly re-entrant (and a clever
- adversary could cause it to never terminate).
- */
-
- b = newblock(0);
- if (b == NULL) {
- PyErr_Clear();
- goto alternate_method;
- }
-
- /* Remember the old size, leftblock, and leftindex */
- leftblock = deque->leftblock;
- leftindex = deque->leftindex;
- n = Py_SIZE(deque);
-
- /* Set the deque to be empty using the newly allocated block */
- MARK_END(b->leftlink);
- MARK_END(b->rightlink);
- Py_SIZE(deque) = 0;
- deque->leftblock = b;
- deque->rightblock = b;
- deque->leftindex = CENTER + 1;
- deque->rightindex = CENTER;
- deque->state++;
-
- /* 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) {
- CHECK_NOT_END(leftblock->rightlink);
- prevblock = leftblock;
- leftblock = leftblock->rightlink;
- leftindex = 0;
- freeblock(prevblock);
- }
- }
- CHECK_END(leftblock->rightlink);
- freeblock(leftblock);
- return;
-
- alternate_method:
- while (Py_SIZE(deque)) {
- item = deque_pop(deque, NULL);
- assert (item != NULL);
- Py_DECREF(item);
- }
-}
-
static int
valid_index(Py_ssize_t i, Py_ssize_t limit)
{
@@ -1229,15 +1269,6 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
return 0;
}
-static PyObject *
-deque_clearmethod(dequeobject *deque)
-{
- deque_clear(deque);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(clear_doc, "Remove all elements from the deque.");
-
static void
deque_dealloc(dequeobject *deque)
{
@@ -1277,41 +1308,6 @@ deque_traverse(dequeobject *deque, visitproc visit, void *arg)
}
static PyObject *
-deque_copy(PyObject *deque)
-{
- dequeobject *old_deque = (dequeobject *)deque;
- if (Py_TYPE(deque) == &deque_type) {
- dequeobject *new_deque;
- PyObject *rv;
-
- new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL);
- if (new_deque == NULL)
- return NULL;
- new_deque->maxlen = old_deque->maxlen;
- /* Fast path for the deque_repeat() common case where len(deque) == 1 */
- if (Py_SIZE(deque) == 1 && new_deque->maxlen != 0) {
- PyObject *item = old_deque->leftblock->data[old_deque->leftindex];
- rv = deque_append(new_deque, item);
- } else {
- rv = deque_extend(new_deque, deque);
- }
- if (rv != NULL) {
- Py_DECREF(rv);
- return (PyObject *)new_deque;
- }
- Py_DECREF(new_deque);
- return NULL;
- }
- if (old_deque->maxlen < 0)
- return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "O", deque, NULL);
- else
- return PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
- deque, old_deque->maxlen, NULL);
-}
-
-PyDoc_STRVAR(copy_doc, "Return a shallow copy of a deque.");
-
-static PyObject *
deque_reduce(dequeobject *deque)
{
PyObject *dict, *result, *aslist;