summaryrefslogtreecommitdiff
path: root/odoo/tools/lru.py
diff options
context:
space:
mode:
authorRaphael Collet <rco@openerp.com>2016-09-02 15:58:39 +0200
committerRaphael Collet <rco@openerp.com>2016-09-02 17:28:12 +0200
commit9e64f9f9514194d74e166b032add8511182f2677 (patch)
tree5086710c04c6b923be18a6d1d97b3f0f3a2a9c4a /odoo/tools/lru.py
parent11812b0b9e82b2b1b9041d8250ce01e7b4a5f7ee (diff)
[REF] openerp: move `openerp` to `odoo`
Diffstat (limited to 'odoo/tools/lru.py')
-rw-r--r--odoo/tools/lru.py126
1 files changed, 126 insertions, 0 deletions
diff --git a/odoo/tools/lru.py b/odoo/tools/lru.py
new file mode 100644
index 00000000000..b0ea21bba44
--- /dev/null
+++ b/odoo/tools/lru.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+# taken from http://code.activestate.com/recipes/252524-length-limited-o1-lru-cache-implementation/
+import threading
+from func import synchronized
+
+__all__ = ['LRU']
+
+class LRUNode(object):
+ __slots__ = ['prev', 'next', 'me']
+ def __init__(self, prev, me):
+ self.prev = prev
+ self.me = me
+ self.next = None
+
+class LRU(object):
+ """
+ Implementation of a length-limited O(1) LRU queue.
+ Built for and used by PyPE:
+ http://pype.sourceforge.net
+ Copyright 2003 Josiah Carlson.
+ """
+ def __init__(self, count, pairs=[]):
+ self._lock = threading.RLock()
+ self.count = max(count, 1)
+ self.d = {}
+ self.first = None
+ self.last = None
+ for key, value in pairs:
+ self[key] = value
+
+ @synchronized()
+ def __contains__(self, obj):
+ return obj in self.d
+
+ def get(self, obj, val=None):
+ try:
+ return self[obj]
+ except KeyError:
+ return val
+
+ @synchronized()
+ def __getitem__(self, obj):
+ a = self.d[obj].me
+ self[a[0]] = a[1]
+ return a[1]
+
+ @synchronized()
+ def __setitem__(self, obj, val):
+ if obj in self.d:
+ del self[obj]
+ nobj = LRUNode(self.last, (obj, val))
+ if self.first is None:
+ self.first = nobj
+ if self.last:
+ self.last.next = nobj
+ self.last = nobj
+ self.d[obj] = nobj
+ if len(self.d) > self.count:
+ if self.first == self.last:
+ self.first = None
+ self.last = None
+ return
+ a = self.first
+ a.next.prev = None
+ self.first = a.next
+ a.next = None
+ del self.d[a.me[0]]
+ del a
+
+ @synchronized()
+ def __delitem__(self, obj):
+ nobj = self.d[obj]
+ if nobj.prev:
+ nobj.prev.next = nobj.next
+ else:
+ self.first = nobj.next
+ if nobj.next:
+ nobj.next.prev = nobj.prev
+ else:
+ self.last = nobj.prev
+ del self.d[obj]
+
+ @synchronized()
+ def __iter__(self):
+ cur = self.first
+ while cur is not None:
+ cur2 = cur.next
+ yield cur.me[1]
+ cur = cur2
+
+ @synchronized()
+ def __len__(self):
+ return len(self.d)
+
+ @synchronized()
+ def iteritems(self):
+ cur = self.first
+ while cur is not None:
+ cur2 = cur.next
+ yield cur.me
+ cur = cur2
+
+ @synchronized()
+ def iterkeys(self):
+ return iter(self.d)
+
+ @synchronized()
+ def itervalues(self):
+ for i,j in self.iteritems():
+ yield j
+
+ @synchronized()
+ def keys(self):
+ return self.d.keys()
+
+ @synchronized()
+ def pop(self,key):
+ v=self[key]
+ del self[key]
+ return v
+
+ @synchronized()
+ def clear(self):
+ self.d = {}
+ self.first = None
+ self.last = None