mirror of https://github.com/python/cpython.git
Improve and fix-up comments.
This commit is contained in:
parent
0f1451c8c0
commit
551350a79f
|
@ -23,31 +23,51 @@
|
||||||
#define BLOCKLEN 64
|
#define BLOCKLEN 64
|
||||||
#define CENTER ((BLOCKLEN - 1) / 2)
|
#define CENTER ((BLOCKLEN - 1) / 2)
|
||||||
|
|
||||||
/* A `dequeobject` is composed of a doubly-linked list of `block` nodes.
|
/* Data for deque objects is stored in a doubly-linked list of fixed
|
||||||
|
* length blocks. This assures that appends or pops never move any
|
||||||
|
* other data elements besides the one being appended or popped.
|
||||||
|
*
|
||||||
|
* Another advantage is that it completely avoids use of realloc(),
|
||||||
|
* resulting in more predictable performance.
|
||||||
|
*
|
||||||
|
* Textbook implementations of doubly-linked lists store one datum
|
||||||
|
* per link, but that gives them a 200% memory overhead (a prev and
|
||||||
|
* next link for each datum) and it costs one malloc() call per data
|
||||||
|
* element. By using fixed-length blocks, the link to data ratio is
|
||||||
|
* significantly improved and there are proportionally fewer calls
|
||||||
|
* to malloc() and free(). The data blocks of consecutive pointers
|
||||||
|
* also improve cache locality.
|
||||||
|
*
|
||||||
* The list of blocks is never empty, so d.leftblock and d.rightblock
|
* The list of blocks is never empty, so d.leftblock and d.rightblock
|
||||||
* are never equal to NULL. The list is not circular.
|
* are never equal to NULL. The list is not circular.
|
||||||
*
|
*
|
||||||
* A deque d's first element is at d.leftblock[leftindex]
|
* A deque d's first element is at d.leftblock[leftindex]
|
||||||
* and its last element is at d.rightblock[rightindex].
|
* and its last element is at d.rightblock[rightindex].
|
||||||
* Unlike Python slice indices, these indices are inclusive
|
|
||||||
* on both ends. This makes the algorithms for left and
|
|
||||||
* right operations more symmetrical and simplifies the design.
|
|
||||||
*
|
*
|
||||||
* The indices, d.leftindex and d.rightindex are always in the range
|
* Unlike Python slice indices, these indices are inclusive on both
|
||||||
* 0 <= index < BLOCKLEN.
|
* ends. This makes the algorithms for left and right operations
|
||||||
* Their exact relationship is:
|
* more symmetrical and it simplifies the design.
|
||||||
* (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex.
|
|
||||||
*
|
*
|
||||||
* Empty deques have d.len == 0; d.leftblock==d.rightblock;
|
* The indices, d.leftindex and d.rightindex are always in the range:
|
||||||
* d.leftindex == CENTER+1; and d.rightindex == CENTER.
|
* 0 <= index < BLOCKLEN
|
||||||
* Checking for d.len == 0 is the intended way to see whether d is empty.
|
*
|
||||||
|
* And their exact relationship is:
|
||||||
|
* (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex
|
||||||
*
|
*
|
||||||
* Whenever d.leftblock == d.rightblock,
|
* Whenever d.leftblock == d.rightblock,
|
||||||
* d.leftindex + d.len - 1 == d.rightindex.
|
* d.leftindex + d.len - 1 == d.rightindex
|
||||||
*
|
*
|
||||||
* However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex
|
* However, when d.leftblock != d.rightblock, the d.leftindex and
|
||||||
* become indices into distinct blocks and either may be larger than the
|
* d.rightindex become indices into distinct blocks and either may
|
||||||
* other.
|
* be larger than the other.
|
||||||
|
*
|
||||||
|
* Empty deques have:
|
||||||
|
* d.len == 0
|
||||||
|
* d.leftblock == d.rightblock
|
||||||
|
* d.leftindex == CENTER + 1
|
||||||
|
* d.rightindex == CENTER
|
||||||
|
*
|
||||||
|
* Checking for d.len == 0 is the intended way to see whether d is empty.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct BLOCK {
|
typedef struct BLOCK {
|
||||||
|
@ -60,8 +80,8 @@ typedef struct {
|
||||||
PyObject_VAR_HEAD
|
PyObject_VAR_HEAD
|
||||||
block *leftblock;
|
block *leftblock;
|
||||||
block *rightblock;
|
block *rightblock;
|
||||||
Py_ssize_t leftindex; /* in range(BLOCKLEN) */
|
Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */
|
||||||
Py_ssize_t rightindex; /* in range(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;
|
||||||
PyObject *weakreflist;
|
PyObject *weakreflist;
|
||||||
|
@ -91,7 +111,7 @@ static PyTypeObject deque_type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* A simple freelisting scheme is used to minimize calls to the memory
|
/* A simple freelisting scheme is used to minimize calls to the memory
|
||||||
allocator. It accomodates common use cases where new blocks are being
|
allocator. It accommodates common use cases where new blocks are being
|
||||||
added at about the same rate as old blocks are being freed.
|
added at about the same rate as old blocks are being freed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -816,6 +836,14 @@ PyDoc_STRVAR(index_doc,
|
||||||
"D.index(value, [start, [stop]]) -> integer -- return first index of value.\n"
|
"D.index(value, [start, [stop]]) -> integer -- return first index of value.\n"
|
||||||
"Raises ValueError if the value is not present.");
|
"Raises ValueError if the value is not present.");
|
||||||
|
|
||||||
|
/* insert(), remove(), and delitem() are implemented in terms of
|
||||||
|
rotate() for simplicity and reasonable performance near the end
|
||||||
|
points. If for some reason these methods become popular, it is not
|
||||||
|
hard to re-implement this using direct data movement (similar to
|
||||||
|
the code used in list slice assignments) and achieve a performance
|
||||||
|
boost (by moving each pointer only one instead of twice).
|
||||||
|
*/
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
deque_insert(dequeobject *deque, PyObject *args)
|
deque_insert(dequeobject *deque, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -945,13 +973,6 @@ deque_item(dequeobject *deque, Py_ssize_t i)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delitem() implemented in terms of rotate for simplicity and reasonable
|
|
||||||
performance near the end points. If for some reason this method becomes
|
|
||||||
popular, it is not hard to re-implement this using direct data movement
|
|
||||||
(similar to code in list slice assignment) and achieve a two or threefold
|
|
||||||
performance boost.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
deque_del_item(dequeobject *deque, Py_ssize_t i)
|
deque_del_item(dequeobject *deque, Py_ssize_t i)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue