[Python-checkins] lru_cache: Add more comments. Fix comment typos. Clarify a comment. (GH-11795) (GH-11798)

Raymond Hettinger webhook-mailer at python.org
Fri Feb 8 22:33:09 EST 2019


https://github.com/python/cpython/commit/7c7839329c2c66d051960ab1df096aed1cc9343e
commit: 7c7839329c2c66d051960ab1df096aed1cc9343e
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: Raymond Hettinger <rhettinger at users.noreply.github.com>
date: 2019-02-08T19:33:06-08:00
summary:

lru_cache:  Add more comments. Fix comment typos. Clarify a comment. (GH-11795) (GH-11798)

files:
M Modules/_functoolsmodule.c

diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 90c698ee41e4..c6a92ed16959 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -661,6 +661,26 @@ sequence is empty.");
 
 /* lru_cache object **********************************************************/
 
+/* There are four principal algorithmic differences from the pure python version:
+
+   1). The C version relies on the GIL instead of having its own reentrant lock.
+
+   2). The prev/next link fields use borrowed references.
+
+   3). For a full cache, the pure python version rotates the location of the
+       root entry so that it never has to move individual links and it can
+       limit updates to just the key and result fields.  However, in the C
+       version, links are temporarily removed while the cache dict updates are
+       occurring. Afterwards, they are appended or prepended back into the
+       doubly-linked lists.
+
+   4)  In the Python version, the _HashSeq class is used to prevent __hash__
+       from being called more than once.  In the C version, the "known hash"
+       variants of dictionary calls as used to the same effect.
+
+*/
+
+
 /* this object is used delimit args and keywords in the cache keys */
 static PyObject *kwd_mark = NULL;
 
@@ -1009,14 +1029,15 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
     link = self->root.next;
     lru_cache_extract_link(link);
     /* Remove it from the cache.
-       The cache dict holds one reference to the link,
-       and the linked list holds yet one reference to it. */
+       The cache dict holds one reference to the link.
+       We created one other reference when the link was created.
+       The linked list only has borrowed references. */
     popresult = _PyDict_Pop_KnownHash(self->cache, link->key,
                                       link->hash, Py_None);
     if (popresult == Py_None) {
         /* Getting here means that the user function call or another
            thread has already removed the old key from the dictionary.
-           This link is now an orpan.  Since we don't want to leave the
+           This link is now an orphan.  Since we don't want to leave the
            cache in an inconsistent state, we don't restore the link. */
         Py_DECREF(popresult);
         Py_DECREF(link);
@@ -1048,7 +1069,7 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
        prev and next fields set to valid values.   We have to wait
        for successful insertion in the cache dict before adding the
        link to the linked list.  Otherwise, the potentially reentrant
-       __eq__ call could cause the then ophan link to be visited. */
+       __eq__ call could cause the then orphan link to be visited. */
     if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
                                   hash) < 0) {
         /* Somehow the cache dict update failed.  We no longer can



More information about the Python-checkins mailing list