Welcome, guest | Sign In | My Account | Store | Cart
class LRU_Cache:

    def __init__(self, user_function, maxsize=1024):
        # Link layout:     [PREV, NEXT, KEY, RESULT]
        self.root = root = [None, None, None, None]
        self.user_function = user_function
        self.cache = cache = {}

        last = root
        for i in range(maxsize):
            key = object()
            cache[key] = last[1] = last = [last, root, key, None]
        root[0] = last

    def __call__(self, *key):
        cache = self.cache
        root = self.root
        link = cache.get(key)
        if link is not None:
            link_prev, link_next, _, result = link
            link_prev[1] = link_next
            link_next[0] = link_prev
            last = root[0]
            last[1] = root[0] = link
            link[0] = last
            link[1] = root
            return result
        result = self.user_function(*key)
        root[2] = key
        root[3] = result
        oldroot = root
        root = self.root = root[1]
        root[2], oldkey = None, root[2]
        root[3], oldvalue = None, root[3]
        del cache[oldkey]
        cache[key] = oldroot
        return result


if __name__ == '__main__':
    p = LRU_Cache(ord, maxsize=3)
    for c in 'abcdecaeaa':
        print(c, p(c))

Diff to Previous Revision

--- revision 5 2012-03-17 21:25:12
+++ revision 6 2013-03-06 06:04:18
@@ -1,39 +1,43 @@
 class LRU_Cache:
 
-    def __init__(self, original_function, maxsize=1000):
-        self.original_function = original_function
-        self.maxsize = maxsize
-        self.mapping = {}
-        self.root = []
-        self.root[:] = self.root, self.root, None, None
+    def __init__(self, user_function, maxsize=1024):
+        # Link layout:     [PREV, NEXT, KEY, RESULT]
+        self.root = root = [None, None, None, None]
+        self.user_function = user_function
+        self.cache = cache = {}
+
+        last = root
+        for i in range(maxsize):
+            key = object()
+            cache[key] = last[1] = last = [last, root, key, None]
+        root[0] = last
 
     def __call__(self, *key):
-        PREV, NEXT = 0, 1
-        mapping, root = self.mapping, self.root
-
-        link = mapping.get(key, root)
-        if link is root:
-            value = self.original_function(*key)
-            if len(mapping) >= self.maxsize:
-                old_prev, old_next, old_key, old_value = root[NEXT]
-                root[NEXT] = old_next
-                old_next[PREV] = root
-                del mapping[old_key]
-            last = root[PREV]
-            link = [last, root, key, value]
-            mapping[key] = last[NEXT] = root[PREV] = link
-        else:
-            link_prev, link_next, key, value = link
-            link_prev[NEXT] = link_next
-            link_next[PREV] = link_prev
-            last = root[PREV]
-            last[NEXT] = root[PREV] = link
-            link[PREV] = last
-            link[NEXT] = root
-        return value
+        cache = self.cache
+        root = self.root
+        link = cache.get(key)
+        if link is not None:
+            link_prev, link_next, _, result = link
+            link_prev[1] = link_next
+            link_next[0] = link_prev
+            last = root[0]
+            last[1] = root[0] = link
+            link[0] = last
+            link[1] = root
+            return result
+        result = self.user_function(*key)
+        root[2] = key
+        root[3] = result
+        oldroot = root
+        root = self.root = root[1]
+        root[2], oldkey = None, root[2]
+        root[3], oldvalue = None, root[3]
+        del cache[oldkey]
+        cache[key] = oldroot
+        return result
 
 
 if __name__ == '__main__':
-    p = LRU_Cache(pow, maxsize=3)
-    for i in [1,2,3,4,5,3,1,5,1,1]:
-        print(i, p(i, 2))
+    p = LRU_Cache(ord, maxsize=3)
+    for c in 'abcdecaeaa':
+        print(c, p(c))

History