diff --git a/odoo/tools/lru.py b/odoo/tools/lru.py index 119fce0e1ee..ba235a3e345 100644 --- a/odoo/tools/lru.py +++ b/odoo/tools/lru.py @@ -1,31 +1,21 @@ # -*- coding: utf-8 -*- -# taken from http://code.activestate.com/recipes/252524-length-limited-o1-lru-cache-implementation/ +import collections 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. + Implementation of a length-limited O(1) LRU map. + + Original Copyright 2003 Josiah Carlson, later rebuilt on OrderedDict. """ - def __init__(self, count, pairs=[]): + def __init__(self, count, pairs=()): self._lock = threading.RLock() self.count = max(count, 1) - self.d = {} - self.first = None - self.last = None + self.d = collections.OrderedDict() for key, value in pairs: self[key] = value @@ -41,88 +31,29 @@ class LRU(object): @synchronized() def __getitem__(self, obj): - a = self.d[obj].me - self[a[0]] = a[1] - return a[1] + a = self.d[obj] + self.d.move_to_end(obj, last=False) + return a @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 + self.d[obj] = val + self.d.move_to_end(obj, last=False) + while len(self.d) > self.count: + self.d.popitem(last=True) @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) - # FIXME: should this have a P2 and a P3 version or something? - @synchronized() - def iteritems(self): - cur = self.first - while cur is not None: - cur2 = cur.next - yield cur.me - cur = cur2 - items = iteritems - - @synchronized() - def iterkeys(self): - return iter(self.d) - - @synchronized() - def itervalues(self): - return iter(self.d.values()) - - @synchronized() - def keys(self): - return list(self.d) - @synchronized() def pop(self,key): - v=self[key] - del self[key] - return v + return self.d.pop(key) @synchronized() def clear(self): - self.d = {} - self.first = None - self.last = None + self.d.clear()