mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	Improve deque iteration.
* The default __reversed__ performed badly, so reintroduced a custom reverse iterator. * Added length transparency to improve speed with map(), list(), etc.
This commit is contained in:
		
							parent
							
								
									ade08ea8a8
								
							
						
					
					
						commit
						1e5809ff02
					
				
					 1 changed files with 102 additions and 1 deletions
				
			
		| 
						 | 
					@ -645,6 +645,9 @@ static PySequenceMethods deque_as_sequence = {
 | 
				
			||||||
/* deque object ********************************************************/
 | 
					/* deque object ********************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PyObject *deque_iter(dequeobject *deque);
 | 
					static PyObject *deque_iter(dequeobject *deque);
 | 
				
			||||||
 | 
					static PyObject *deque_reviter(dequeobject *deque);
 | 
				
			||||||
 | 
					PyDoc_STRVAR(reversed_doc, 
 | 
				
			||||||
 | 
						"D.__reversed__() -- return a reverse iterator over the deque");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static PyMethodDef deque_methods[] = {
 | 
					static PyMethodDef deque_methods[] = {
 | 
				
			||||||
	{"append",		(PyCFunction)deque_append,	
 | 
						{"append",		(PyCFunction)deque_append,	
 | 
				
			||||||
| 
						 | 
					@ -665,6 +668,8 @@ static PyMethodDef deque_methods[] = {
 | 
				
			||||||
		METH_NOARGS,	 popleft_doc},
 | 
							METH_NOARGS,	 popleft_doc},
 | 
				
			||||||
	{"__reduce__",	(PyCFunction)deque_reduce,	
 | 
						{"__reduce__",	(PyCFunction)deque_reduce,	
 | 
				
			||||||
		METH_NOARGS,	 reduce_doc},
 | 
							METH_NOARGS,	 reduce_doc},
 | 
				
			||||||
 | 
						{"__reversed__",	(PyCFunction)deque_reviter,	
 | 
				
			||||||
 | 
							METH_NOARGS,	 reversed_doc},
 | 
				
			||||||
	{"rotate",		(PyCFunction)deque_rotate,	
 | 
						{"rotate",		(PyCFunction)deque_rotate,	
 | 
				
			||||||
		METH_VARARGS,	rotate_doc},
 | 
							METH_VARARGS,	rotate_doc},
 | 
				
			||||||
	{NULL,		NULL}	/* sentinel */
 | 
						{NULL,		NULL}	/* sentinel */
 | 
				
			||||||
| 
						 | 
					@ -727,6 +732,7 @@ typedef struct {
 | 
				
			||||||
	block *b;
 | 
						block *b;
 | 
				
			||||||
	dequeobject *deque;
 | 
						dequeobject *deque;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
						int counter;
 | 
				
			||||||
} dequeiterobject;
 | 
					} dequeiterobject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyTypeObject dequeiter_type;
 | 
					PyTypeObject dequeiter_type;
 | 
				
			||||||
| 
						 | 
					@ -744,6 +750,7 @@ deque_iter(dequeobject *deque)
 | 
				
			||||||
	Py_INCREF(deque);
 | 
						Py_INCREF(deque);
 | 
				
			||||||
	it->deque = deque;
 | 
						it->deque = deque;
 | 
				
			||||||
	it->len = deque->len;
 | 
						it->len = deque->len;
 | 
				
			||||||
 | 
						it->counter = deque->len;
 | 
				
			||||||
	return (PyObject *)it;
 | 
						return (PyObject *)it;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -774,10 +781,22 @@ dequeiter_next(dequeiterobject *it)
 | 
				
			||||||
		it->b = it->b->rightlink;
 | 
							it->b = it->b->rightlink;
 | 
				
			||||||
		it->index = 0;
 | 
							it->index = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						it->counter--;
 | 
				
			||||||
	Py_INCREF(item);
 | 
						Py_INCREF(item);
 | 
				
			||||||
	return item;
 | 
						return item;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					dequeiter_len(dequeiterobject *it)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return it->counter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PySequenceMethods dequeiter_as_sequence = {
 | 
				
			||||||
 | 
						(inquiry)dequeiter_len,		/* sq_length */
 | 
				
			||||||
 | 
						0,				/* sq_concat */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyTypeObject dequeiter_type = {
 | 
					PyTypeObject dequeiter_type = {
 | 
				
			||||||
	PyObject_HEAD_INIT(NULL)
 | 
						PyObject_HEAD_INIT(NULL)
 | 
				
			||||||
	0,					/* ob_size */
 | 
						0,					/* ob_size */
 | 
				
			||||||
| 
						 | 
					@ -792,7 +811,7 @@ PyTypeObject dequeiter_type = {
 | 
				
			||||||
	0,					/* tp_compare */
 | 
						0,					/* tp_compare */
 | 
				
			||||||
	0,					/* tp_repr */
 | 
						0,					/* tp_repr */
 | 
				
			||||||
	0,					/* tp_as_number */
 | 
						0,					/* tp_as_number */
 | 
				
			||||||
	0,					/* tp_as_sequence */
 | 
						&dequeiter_as_sequence,			/* tp_as_sequence */
 | 
				
			||||||
	0,					/* tp_as_mapping */
 | 
						0,					/* tp_as_mapping */
 | 
				
			||||||
	0,					/* tp_hash */
 | 
						0,					/* tp_hash */
 | 
				
			||||||
	0,					/* tp_call */
 | 
						0,					/* tp_call */
 | 
				
			||||||
| 
						 | 
					@ -811,6 +830,85 @@ PyTypeObject dequeiter_type = {
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*********************** Deque Reverse Iterator **************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyTypeObject dequereviter_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					deque_reviter(dequeobject *deque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dequeiterobject *it;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						it = PyObject_New(dequeiterobject, &dequereviter_type);
 | 
				
			||||||
 | 
						if (it == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						it->b = deque->rightblock;
 | 
				
			||||||
 | 
						it->index = deque->rightindex;
 | 
				
			||||||
 | 
						Py_INCREF(deque);
 | 
				
			||||||
 | 
						it->deque = deque;
 | 
				
			||||||
 | 
						it->len = deque->len;
 | 
				
			||||||
 | 
						it->counter = deque->len;
 | 
				
			||||||
 | 
						return (PyObject *)it;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PyObject *
 | 
				
			||||||
 | 
					dequereviter_next(dequeiterobject *it)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						PyObject *item;
 | 
				
			||||||
 | 
						if (it->b == it->deque->leftblock && it->index < it->deque->leftindex)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (it->len != it->deque->len) {
 | 
				
			||||||
 | 
							it->len = -1; /* Make this state sticky */
 | 
				
			||||||
 | 
							PyErr_SetString(PyExc_RuntimeError,
 | 
				
			||||||
 | 
									"deque changed size during iteration");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						item = it->b->data[it->index];
 | 
				
			||||||
 | 
						it->index--;
 | 
				
			||||||
 | 
						if (it->index == -1 && it->b->leftlink != NULL) {
 | 
				
			||||||
 | 
							it->b = it->b->leftlink;
 | 
				
			||||||
 | 
							it->index = BLOCKLEN - 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						it->counter--;
 | 
				
			||||||
 | 
						Py_INCREF(item);
 | 
				
			||||||
 | 
						return item;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyTypeObject dequereviter_type = {
 | 
				
			||||||
 | 
						PyObject_HEAD_INIT(NULL)
 | 
				
			||||||
 | 
						0,					/* ob_size */
 | 
				
			||||||
 | 
						"deque_reverse_iterator",		/* tp_name */
 | 
				
			||||||
 | 
						sizeof(dequeiterobject),		/* tp_basicsize */
 | 
				
			||||||
 | 
						0,					/* tp_itemsize */
 | 
				
			||||||
 | 
						/* methods */
 | 
				
			||||||
 | 
						(destructor)dequeiter_dealloc,		/* tp_dealloc */
 | 
				
			||||||
 | 
						0,					/* tp_print */
 | 
				
			||||||
 | 
						0,					/* tp_getattr */
 | 
				
			||||||
 | 
						0,					/* tp_setattr */
 | 
				
			||||||
 | 
						0,					/* tp_compare */
 | 
				
			||||||
 | 
						0,					/* tp_repr */
 | 
				
			||||||
 | 
						0,					/* tp_as_number */
 | 
				
			||||||
 | 
						&dequeiter_as_sequence,			/* tp_as_sequence */
 | 
				
			||||||
 | 
						0,					/* tp_as_mapping */
 | 
				
			||||||
 | 
						0,					/* tp_hash */
 | 
				
			||||||
 | 
						0,					/* tp_call */
 | 
				
			||||||
 | 
						0,					/* tp_str */
 | 
				
			||||||
 | 
						PyObject_GenericGetAttr,		/* tp_getattro */
 | 
				
			||||||
 | 
						0,					/* tp_setattro */
 | 
				
			||||||
 | 
						0,					/* tp_as_buffer */
 | 
				
			||||||
 | 
						Py_TPFLAGS_DEFAULT,			/* tp_flags */
 | 
				
			||||||
 | 
						0,					/* tp_doc */
 | 
				
			||||||
 | 
						0,					/* tp_traverse */
 | 
				
			||||||
 | 
						0,					/* tp_clear */
 | 
				
			||||||
 | 
						0,					/* tp_richcompare */
 | 
				
			||||||
 | 
						0,					/* tp_weaklistoffset */
 | 
				
			||||||
 | 
						PyObject_SelfIter,			/* tp_iter */
 | 
				
			||||||
 | 
						(iternextfunc)dequereviter_next,	/* tp_iternext */
 | 
				
			||||||
 | 
						0,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* module level code ********************************************************/
 | 
					/* module level code ********************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyDoc_STRVAR(module_doc,
 | 
					PyDoc_STRVAR(module_doc,
 | 
				
			||||||
| 
						 | 
					@ -832,5 +930,8 @@ initcollections(void)
 | 
				
			||||||
	if (PyType_Ready(&dequeiter_type) < 0)
 | 
						if (PyType_Ready(&dequeiter_type) < 0)
 | 
				
			||||||
		return;	
 | 
							return;	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (PyType_Ready(&dequereviter_type) < 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue