Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 551350a

Browse files
committed
Improve and fix-up comments.
1 parent 0f1451c commit 551350a

1 file changed

Lines changed: 46 additions & 25 deletions

File tree

Modules/_collectionsmodule.c

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,51 @@
2323
#define BLOCKLEN 64
2424
#define CENTER ((BLOCKLEN - 1) / 2)
2525

26-
/* A `dequeobject` is composed of a doubly-linked list of `block` nodes.
26+
/* Data for deque objects is stored in a doubly-linked list of fixed
27+
* length blocks. This assures that appends or pops never move any
28+
* other data elements besides the one being appended or popped.
29+
*
30+
* Another advantage is that it completely avoids use of realloc(),
31+
* resulting in more predictable performance.
32+
*
33+
* Textbook implementations of doubly-linked lists store one datum
34+
* per link, but that gives them a 200% memory overhead (a prev and
35+
* next link for each datum) and it costs one malloc() call per data
36+
* element. By using fixed-length blocks, the link to data ratio is
37+
* significantly improved and there are proportionally fewer calls
38+
* to malloc() and free(). The data blocks of consecutive pointers
39+
* also improve cache locality.
40+
*
2741
* The list of blocks is never empty, so d.leftblock and d.rightblock
2842
* are never equal to NULL. The list is not circular.
2943
*
3044
* A deque d's first element is at d.leftblock[leftindex]
3145
* and its last element is at d.rightblock[rightindex].
32-
* Unlike Python slice indices, these indices are inclusive
33-
* on both ends. This makes the algorithms for left and
34-
* right operations more symmetrical and simplifies the design.
3546
*
36-
* The indices, d.leftindex and d.rightindex are always in the range
37-
* 0 <= index < BLOCKLEN.
38-
* Their exact relationship is:
39-
* (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex.
47+
* Unlike Python slice indices, these indices are inclusive on both
48+
* ends. This makes the algorithms for left and right operations
49+
* more symmetrical and it simplifies the design.
4050
*
41-
* Empty deques have d.len == 0; d.leftblock==d.rightblock;
42-
* d.leftindex == CENTER+1; and d.rightindex == CENTER.
43-
* Checking for d.len == 0 is the intended way to see whether d is empty.
51+
* The indices, d.leftindex and d.rightindex are always in the range:
52+
* 0 <= index < BLOCKLEN
53+
*
54+
* And their exact relationship is:
55+
* (d.leftindex + d.len - 1) % BLOCKLEN == d.rightindex
4456
*
4557
* Whenever d.leftblock == d.rightblock,
46-
* d.leftindex + d.len - 1 == d.rightindex.
58+
* d.leftindex + d.len - 1 == d.rightindex
59+
*
60+
* However, when d.leftblock != d.rightblock, the d.leftindex and
61+
* d.rightindex become indices into distinct blocks and either may
62+
* be larger than the other.
4763
*
48-
* However, when d.leftblock != d.rightblock, d.leftindex and d.rightindex
49-
* become indices into distinct blocks and either may be larger than the
50-
* other.
64+
* Empty deques have:
65+
* d.len == 0
66+
* d.leftblock == d.rightblock
67+
* d.leftindex == CENTER + 1
68+
* d.rightindex == CENTER
69+
*
70+
* Checking for d.len == 0 is the intended way to see whether d is empty.
5171
*/
5272

5373
typedef struct BLOCK {
@@ -60,8 +80,8 @@ typedef struct {
6080
PyObject_VAR_HEAD
6181
block *leftblock;
6282
block *rightblock;
63-
Py_ssize_t leftindex; /* in range(BLOCKLEN) */
64-
Py_ssize_t rightindex; /* in range(BLOCKLEN) */
83+
Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */
84+
Py_ssize_t rightindex; /* 0 <= rightindex < BLOCKLEN */
6585
size_t state; /* incremented whenever the indices move */
6686
Py_ssize_t maxlen;
6787
PyObject *weakreflist;
@@ -91,7 +111,7 @@ static PyTypeObject deque_type;
91111
#endif
92112

93113
/* A simple freelisting scheme is used to minimize calls to the memory
94-
allocator. It accomodates common use cases where new blocks are being
114+
allocator. It accommodates common use cases where new blocks are being
95115
added at about the same rate as old blocks are being freed.
96116
*/
97117

@@ -816,6 +836,14 @@ PyDoc_STRVAR(index_doc,
816836
"D.index(value, [start, [stop]]) -> integer -- return first index of value.\n"
817837
"Raises ValueError if the value is not present.");
818838

839+
/* insert(), remove(), and delitem() are implemented in terms of
840+
rotate() for simplicity and reasonable performance near the end
841+
points. If for some reason these methods become popular, it is not
842+
hard to re-implement this using direct data movement (similar to
843+
the code used in list slice assignments) and achieve a performance
844+
boost (by moving each pointer only one instead of twice).
845+
*/
846+
819847
static PyObject *
820848
deque_insert(dequeobject *deque, PyObject *args)
821849
{
@@ -945,13 +973,6 @@ deque_item(dequeobject *deque, Py_ssize_t i)
945973
return item;
946974
}
947975

948-
/* delitem() implemented in terms of rotate for simplicity and reasonable
949-
performance near the end points. If for some reason this method becomes
950-
popular, it is not hard to re-implement this using direct data movement
951-
(similar to code in list slice assignment) and achieve a two or threefold
952-
performance boost.
953-
*/
954-
955976
static int
956977
deque_del_item(dequeobject *deque, Py_ssize_t i)
957978
{

0 commit comments

Comments
 (0)