[omniORB] python evictor
enrico.sirola@riskmap.it
enrico.sirola@riskmap.it
Mon Mar 3 10:24:02 2003
>>>>> "darryl" == darryl <developer@csrules.dyndns.org> writes:
darryl> has anyone implemented an evictor pattern in python they'd
darryl> like to share?
here we go... It's not very well tested, so i'd like to have some
feedback. Bye,
enrico
--------------------> Evictor.py <--------------------
# Copyright (C) 2003 RiskMap s.r.l. Milano -*-python-*-
#
# RiskMap
# Via G. B. Vico 4
# I-20123 Milano
# ITALY
#
# phone: +39 02 43317510
# fax: +39 02 43911424
#
# email: info@riskmap.net
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.
#
# Author: Enrico Sirola (sirola@fisica.unige.it)
__version__ = "$Revision: 1.3 $"[11:-2]
import UserDict
class Evictor(UserDict.UserDict):
"""
A simple eviction class: to be more pythonic, it works like a dictionary
eviction strategy is LRU.
"""
class _LinkedList:
"""private Linked list implementation, used by the Evictor class only"""
class ListItem:
"""linked list item, used by the Evictor class only"""
def __init__(self, key, value, next = None, prev = None):
self.key = key
self.value = value
self.next = next
self.prev = prev
def __repr__(self):
return str((self.key, self.value))
def __init__(self):
self.first = None
self.last = None
self.size = 0
def append(self, item):
item.prev = self.last
item.next = None
if self.last: self.last.next = item
if not self.first: self.first = item
self.last = item
self.size += 1
return item
def remove(self, item):
p = item.prev
n = item.next
if p: p.next = n
else: self.first = item.next
if n: n.prev = p
else: self.last = item.prev
self.size -= 1
del item
def __init__(self,
itemsFactory,
size):
"""
Evictor(itemsFactory, size):
itemsFactory is a callable object which returns an instance given key (i.e.
a constructor: obviously key must be hashable)
size is the eviction queue size.
"""
self.factory = itemsFactory
self.list = Evictor._LinkedList()
self.data = {}
self.size = size
def __getitem__(self, key):
"""
returns the item related to the given key. if the item is not
in the map, allocates it and returns. It returns KeyError iff
the item constructor fails
TODO: think about KeyError exception
"""
item = self.data.get(key)
if not item:
if self.list.size == self.size:
firstItem = self.list.first
self.list.remove(firstItem)
del self.data[firstItem.key]
item = self.list.append(Evictor._LinkedList.ListItem(key, self.factory(key)))
self.data[key] = item
else:
self.list.remove(item)
self.list.append(item)
return item.value
--
Enrico Sirola <enrico.sirola@riskmap.it>
gpg public key available from www.keyserver.net, Key ID 0x377FE07F
Key fingerprint = B446 7332 ED55 BC68 5FE8 DE0F 98DF EC86 377F E07F