summaryrefslogtreecommitdiffstats
path: root/Modules/_collectionsmodule.c
diff options
context:
space:
mode:
authorRaymond Hettinger <rhettinger@users.noreply.github.com>2020-12-23 19:45:06 (GMT)
committerGitHub <noreply@github.com>2020-12-23 19:45:06 (GMT)
commit6b1ac809b9718a369aea67b99077cdd682be2238 (patch)
tree9afaac712cd56684e4e45684a0fac4e48f950d34 /Modules/_collectionsmodule.c
parenta12491681f08a33abcca843f5150330740c91111 (diff)
downloadcpython-6b1ac809b9718a369aea67b99077cdd682be2238.zip
cpython-6b1ac809b9718a369aea67b99077cdd682be2238.tar.gz
cpython-6b1ac809b9718a369aea67b99077cdd682be2238.tar.bz2
bpo-25246: Optimize deque.remove() (GH-23898)
Diffstat (limited to 'Modules/_collectionsmodule.c')
-rw-r--r--Modules/_collectionsmodule.c74
1 files changed, 42 insertions, 32 deletions
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
index 1578750..90bafb0 100644
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -1128,38 +1128,6 @@ deque_insert(dequeobject *deque, PyObject *const *args, Py_ssize_t nargs)
PyDoc_STRVAR(insert_doc,
"D.insert(index, object) -- insert object before index");
-static PyObject *
-deque_remove(dequeobject *deque, PyObject *value)
-{
- Py_ssize_t i, n=Py_SIZE(deque);
-
- for (i=0 ; i<n ; i++) {
- PyObject *item = deque->leftblock->data[deque->leftindex];
- int cmp = PyObject_RichCompareBool(item, value, Py_EQ);
-
- if (Py_SIZE(deque) != n) {
- PyErr_SetString(PyExc_IndexError,
- "deque mutated during remove().");
- return NULL;
- }
- if (cmp > 0) {
- PyObject *tgt = deque_popleft(deque, NULL);
- assert (tgt != NULL);
- if (_deque_rotate(deque, i))
- return NULL;
- Py_DECREF(tgt);
- Py_RETURN_NONE;
- }
- else if (cmp < 0) {
- _deque_rotate(deque, i);
- return NULL;
- }
- _deque_rotate(deque, -1);
- }
- PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque");
- return NULL;
-}
-
PyDoc_STRVAR(remove_doc,
"D.remove(value) -- remove first occurrence of value.");
@@ -1227,6 +1195,48 @@ deque_del_item(dequeobject *deque, Py_ssize_t i)
return rv;
}
+static PyObject *
+deque_remove(dequeobject *deque, PyObject *value)
+{
+ PyObject *item;
+ block *b = deque->leftblock;
+ Py_ssize_t i, n = Py_SIZE(deque), index = deque->leftindex;
+ size_t start_state = deque->state;
+ int cmp, rv;
+
+ for (i = 0 ; i < n; i++) {
+ item = b->data[index];
+ Py_INCREF(item);
+ cmp = PyObject_RichCompareBool(item, value, Py_EQ);
+ Py_DECREF(item);
+ if (cmp < 0) {
+ return NULL;
+ }
+ if (start_state != deque->state) {
+ PyErr_SetString(PyExc_IndexError,
+ "deque mutated during iteration");
+ return NULL;
+ }
+ if (cmp > 0) {
+ break;
+ }
+ index++;
+ if (index == BLOCKLEN) {
+ b = b->rightlink;
+ index = 0;
+ }
+ }
+ if (i == n) {
+ PyErr_Format(PyExc_ValueError, "%R is not in deque", value);
+ return NULL;
+ }
+ rv = deque_del_item(deque, i);
+ if (rv == -1) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
static int
deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
{