@@ -864,42 +864,56 @@ bounded_lru_cache_wrapper(lru_cache_object *self, PyObject *args, PyObject *kwds
864864 }
865865 if (self -> full && self -> root .next != & self -> root ) {
866866 /* Use the oldest item to store the new key and result. */
867- PyObject * oldkey , * oldresult ;
867+ PyObject * oldkey , * oldresult , * popresult ;
868868 /* Extricate the oldest item. */
869869 link = self -> root .next ;
870870 lru_cache_extricate_link (link );
871871 /* Remove it from the cache.
872872 The cache dict holds one reference to the link,
873873 and the linked list holds yet one reference to it. */
874- if (_PyDict_DelItem_KnownHash (self -> cache , link -> key ,
875- link -> hash ) < 0 ) {
874+ popresult = _PyDict_Pop_KnownHash ((PyDictObject * )self -> cache ,
875+ link -> key , link -> hash ,
876+ Py_None );
877+ if (popresult == Py_None ) {
878+ /* Getting here means that this same key was added to the
879+ cache while the lock was released. Since the link
880+ update is already done, we need only return the
881+ computed result and update the count of misses. */
882+ Py_DECREF (popresult );
883+ Py_DECREF (link );
884+ Py_DECREF (key );
885+ }
886+ else if (popresult == NULL ) {
876887 lru_cache_append_link (self , link );
877888 Py_DECREF (key );
878889 Py_DECREF (result );
879890 return NULL ;
880891 }
881- /* Keep a reference to the old key and old result to
882- prevent their ref counts from going to zero during the
883- update. That will prevent potentially arbitrary object
884- clean-up code (i.e. __del__) from running while we're
885- still adjusting the links. */
886- oldkey = link -> key ;
887- oldresult = link -> result ;
888-
889- link -> hash = hash ;
890- link -> key = key ;
891- link -> result = result ;
892- if (_PyDict_SetItem_KnownHash (self -> cache , key , (PyObject * )link ,
893- hash ) < 0 ) {
894- Py_DECREF (link );
892+ else {
893+ Py_DECREF (popresult );
894+ /* Keep a reference to the old key and old result to
895+ prevent their ref counts from going to zero during the
896+ update. That will prevent potentially arbitrary object
897+ clean-up code (i.e. __del__) from running while we're
898+ still adjusting the links. */
899+ oldkey = link -> key ;
900+ oldresult = link -> result ;
901+
902+ link -> hash = hash ;
903+ link -> key = key ;
904+ link -> result = result ;
905+ if (_PyDict_SetItem_KnownHash (self -> cache , key , (PyObject * )link ,
906+ hash ) < 0 ) {
907+ Py_DECREF (link );
908+ Py_DECREF (oldkey );
909+ Py_DECREF (oldresult );
910+ return NULL ;
911+ }
912+ lru_cache_append_link (self , link );
913+ Py_INCREF (result ); /* for return */
895914 Py_DECREF (oldkey );
896915 Py_DECREF (oldresult );
897- return NULL ;
898916 }
899- lru_cache_append_link (self , link );
900- Py_INCREF (result ); /* for return */
901- Py_DECREF (oldkey );
902- Py_DECREF (oldresult );
903917 } else {
904918 /* Put result in a new link at the front of the queue. */
905919 link = (lru_list_elem * )PyObject_GC_New (lru_list_elem ,
0 commit comments