E5Utilities/E5Cache.py

changeset 5909
21d90a3abc7c
parent 5903
7e7002215f9e
child 5910
3f0255a8786a
equal deleted inserted replaced
5908:4d08fb83a844 5909:21d90a3abc7c
6 """ 6 """
7 Module implementing classes used for caching objects. 7 Module implementing classes used for caching objects.
8 """ 8 """
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import QDateTime, QTimer
11 13
12 14
13 # TODO: add timeout for cached entries 15 # TODO: add timeout for cached entries
14 class E5Cache(object): 16 class E5Cache(object):
15 """ 17 """
30 32
31 self.__size = size 33 self.__size = size
32 34
33 # internal objects 35 # internal objects
34 self.__keyList = [] 36 self.__keyList = []
35 self.__store = {} 37 self.__store = {} # stores the cache entries
38 self.__accesStore = {} # stores the last access date and times
36 self.__hits = 0 39 self.__hits = 0
37 self.__misses = 0 40 self.__misses = 0
38 self.__maxsize = 0 41 self.__maxsize = 0
42 self.__maxCacheTime = 0 # 0 seconds means aging is disabled
43
44 self.__cacheTimer = QTimer()
45 self.__cacheTimer.setSingleShot(True)
46 self.__cacheTimer.timeout.connect(self.__pruneCache)
39 47
40 def __moveLast(self, key): 48 def __moveLast(self, key):
41 """ 49 """
42 Private method to move a cached item to the MRU position. 50 Private method to move a cached item to the MRU position.
43 51
53 """ 61 """
54 removeList, self.__keyList = \ 62 removeList, self.__keyList = \
55 self.__keyList[:-self.__size], self.__keyList[-self.__size:] 63 self.__keyList[:-self.__size], self.__keyList[-self.__size:]
56 for key in removeList: 64 for key in removeList:
57 del self.__store[key] 65 del self.__store[key]
66 del self.__accesStore[key]
58 67
59 def getSize(self): 68 def getSize(self):
60 """ 69 """
61 Public method to get the maximum size of the cache. 70 Public method to get the maximum size of the cache.
62 71
76 assert newSize >= 0 85 assert newSize >= 0
77 86
78 self.__size = newSize 87 self.__size = newSize
79 self.__adjustToSize() 88 self.__adjustToSize()
80 89
90 def getMaximumCacheTime(self):
91 """
92 Public method to get the maximum time entries may exist in the cache.
93
94 @return maximum cache time in seconds
95 @rtype int
96 """
97 return self.__maxCacheTime
98
99 def setMaximumCacheTime(self, time):
100 """
101 Public method to set the maximum time entries may exist in the cache.
102
103 @param time maximum cache time in seconds
104 @type int
105 """
106 if time != self.__maxCacheTime:
107 self.__cacheTimer.stop()
108 self.__pruneCache()
109 self.__maxCacheTime = time
110 if self.__maxCacheTime > 0:
111 self.__cacheTimer.setInterval(self.__maxCacheTime * 1000)
112 self.__cacheTimer.start()
113
81 def get(self, key): 114 def get(self, key):
82 """ 115 """
83 Public method to get an entry from the cache given its key. 116 Public method to get an entry from the cache given its key.
84 117
85 If the key is present in the cache, it is moved to the MRU position. 118 If the key is present in the cache, it is moved to the MRU position.
91 @rtype object or None 124 @rtype object or None
92 """ 125 """
93 if key in self.__store: 126 if key in self.__store:
94 self.__hits += 1 127 self.__hits += 1
95 self.__moveLast(key) 128 self.__moveLast(key)
129 self.__accesStore[key] = QDateTime.currentDateTimeUtc()
96 return self.__store[key] 130 return self.__store[key]
97 else: 131 else:
98 self.__misses += 1 132 self.__misses += 1
99 return None 133 return None
100 134
113 if key in self.__store: 147 if key in self.__store:
114 self.__moveLast(key) 148 self.__moveLast(key)
115 else: 149 else:
116 self.__keyList.append(key) 150 self.__keyList.append(key)
117 self.__store[key] = item 151 self.__store[key] = item
152 self.__accesStore[key] = QDateTime.currentDateTimeUtc()
118 153
119 self.__adjustToSize() 154 self.__adjustToSize()
120 155
121 self.__maxsize = max(self.__maxsize, len(self.__keyList)) 156 self.__maxsize = max(self.__maxsize, len(self.__keyList))
122 157
127 @param key key of the item to be retrieved 162 @param key key of the item to be retrieved
128 @type any hashable type that can be used as a dict key 163 @type any hashable type that can be used as a dict key
129 """ 164 """
130 if key in self.__store: 165 if key in self.__store:
131 del self.__store[key] 166 del self.__store[key]
167 del self.__accesStore[key]
132 self.__keyList.remove(key) 168 self.__keyList.remove(key)
133 169
134 def clear(self): 170 def clear(self):
135 """ 171 """
136 Public method to clear the cache. 172 Public method to clear the cache.
137 """ 173 """
138 self.__keyList = [] 174 self.__keyList = []
139 self.__store = {} 175 self.__store = {}
176 self.__accesStore = {}
140 177
141 def reset(self): 178 def reset(self):
142 """ 179 """
143 Public method to reset the cache. 180 Public method to reset the cache.
144 181
170 "hits": self.__hits, 207 "hits": self.__hits,
171 "misses": self.__misses, 208 "misses": self.__misses,
172 "maxsize": self.__maxsize, 209 "maxsize": self.__maxsize,
173 "currsize": self.length(), 210 "currsize": self.length(),
174 } 211 }
212
213 def __pruneCache(self):
214 """
215 Private slot to prune outdated cache entries and restart the timer.
216 """
217 if self.__maxCacheTime > 0:
218 current = QDateTime.currentDateTimeUtc()
219
220 keysToBeDeleted = []
221 for key, lastAccessTime in self.__accesStore.items():
222 if lastAccessTime.secsTo(current) > self.__maxCacheTime:
223 keysToBeDeleted.append(key)
224 for key in keysToBeDeleted:
225 self.remove(key)
226
227 self.__cacheTimer.start()

eric ide

mercurial