Package logilab :: Package common :: Module cache
[frames] | no frames]

Source Code for Module logilab.common.cache

  1  # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  2  # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  3  # 
  4  # This file is part of logilab-common. 
  5  # 
  6  # logilab-common is free software: you can redistribute it and/or modify it under 
  7  # the terms of the GNU Lesser General Public License as published by the Free 
  8  # Software Foundation, either version 2.1 of the License, or (at your option) any 
  9  # later version. 
 10  # 
 11  # logilab-common is distributed in the hope that it will be useful, but WITHOUT 
 12  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 13  # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 14  # details. 
 15  # 
 16  # You should have received a copy of the GNU Lesser General Public License along 
 17  # with logilab-common.  If not, see <http://www.gnu.org/licenses/>. 
 18  """Cache module, with a least recently used algorithm for the management of the 
 19  deletion of entries. 
 20   
 21   
 22   
 23   
 24  """ 
 25  __docformat__ = "restructuredtext en" 
 26   
 27  from threading import Lock 
 28   
 29  from logilab.common.decorators import locked 
 30   
 31  _marker = object() 
 32   
33 -class Cache(dict):
34 """A dictionary like cache. 35 36 inv: 37 len(self._usage) <= self.size 38 len(self.data) <= self.size 39 """ 40
41 - def __init__(self, size=100):
42 """ Warning : Cache.__init__() != dict.__init__(). 43 Constructor does not take any arguments beside size. 44 """ 45 assert size >= 0, 'cache size must be >= 0 (0 meaning no caching)' 46 self.size = size 47 self._usage = [] 48 self._lock = Lock() 49 super(Cache, self).__init__()
50
51 - def _acquire(self):
52 self._lock.acquire()
53
54 - def _release(self):
55 self._lock.release()
56
57 - def _update_usage(self, key):
58 if not self._usage: 59 self._usage.append(key) 60 elif self._usage[-1] != key: 61 try: 62 self._usage.remove(key) 63 except ValueError: 64 # we are inserting a new key 65 # check the size of the dictionary 66 # and remove the oldest item in the cache 67 if self.size and len(self._usage) >= self.size: 68 super(Cache, self).__delitem__(self._usage[0]) 69 del self._usage[0] 70 self._usage.append(key) 71 else: 72 pass # key is already the most recently used key
73
74 - def __getitem__(self, key):
75 value = super(Cache, self).__getitem__(key) 76 self._update_usage(key) 77 return value
78 __getitem__ = locked(_acquire, _release)(__getitem__) 79
80 - def __setitem__(self, key, item):
81 # Just make sure that size > 0 before inserting a new item in the cache 82 if self.size > 0: 83 super(Cache, self).__setitem__(key, item) 84 self._update_usage(key)
85 __setitem__ = locked(_acquire, _release)(__setitem__) 86
87 - def __delitem__(self, key):
88 super(Cache, self).__delitem__(key) 89 self._usage.remove(key)
90 __delitem__ = locked(_acquire, _release)(__delitem__) 91
92 - def clear(self):
93 super(Cache, self).clear() 94 self._usage = []
95 clear = locked(_acquire, _release)(clear) 96
97 - def pop(self, key, default=_marker):
98 if key in self: 99 self._usage.remove(key) 100 #if default is _marker: 101 # return super(Cache, self).pop(key) 102 return super(Cache, self).pop(key, default)
103 pop = locked(_acquire, _release)(pop) 104
105 - def popitem(self):
106 raise NotImplementedError()
107
108 - def setdefault(self, key, default=None):
109 raise NotImplementedError()
110
111 - def update(self, other):
112 raise NotImplementedError()
113