Welcome, guest | Sign In | My Account | Store | Cart
class Cache(object):
   
"""
    >>> dec_cache = Cache(10)
    >>> @dec_cache
    ... def identity(f):
    ...     return f
    >>> dummy = [identity(x) for x in range(20) + range(11,15) + range(20) +
    ... range(11,40) + [39, 38, 37, 36, 35, 34, 33, 32, 16, 17, 11, 41]]
    >>> dec_cache.t1
    deque([(41,)])
    >>> dec_cache.t2
    deque([(11,), (17,), (16,), (32,), (33,), (34,), (35,), (36,), (37,)])
    >>> dec_cache.b1
    deque([(31,), (30,)])
    >>> dec_cache.b2
    deque([(38,), (39,), (19,), (18,), (15,), (14,), (13,), (12,)])
    >>> dec_cache.p
    5
    """

   
def __init__(self, size):
       
self.cached = {}
       
self.c = size
       
self.p = 0
       
self.t1 = deque()
       
self.t2 = deque()
       
self.b1 = deque()
       
self.b2 = deque()

   
def replace(self, args):
       
if self.t1 and (
           
(args in self.b2 and len(self.t1) == self.p) or
           
(len(self.t1) > self.p)):
            old
= self.t1.pop()
           
self.b1.appendleft(old)
       
else:
            old
= self.t2.pop()
           
self.b2.appendleft(old)
       
del(self.cached[old])
       
   
def __call__(self, func):
       
def wrapper(*orig_args):
           
"""decorator function wrapper"""
            args
= orig_args[:]
           
if args in self.t1:
               
self.t1.remove(args)
               
self.t2.appendleft(args)
               
return self.cached[args]
           
if args in self.t2:
               
self.t2.remove(args)
               
self.t2.appendleft(args)
               
return self.cached[args]
            result
= func(*orig_args)
           
self.cached[args] = result
           
if args in self.b1:
               
self.p = min(
                   
self.c, self.p + max(len(self.b2) / len(self.b1) , 1))
               
self.replace(args)
               
self.b1.remove(args)
               
self.t2.appendleft(args)
               
#print "%s:: t1:%s b1:%s t2:%s b2:%s p:%s" % (
               
#    repr(func)[10:30], len(self.t1),len(self.b1),len(self.t2),
               
#    len(self.b2), self.p)
               
return result            
           
if args in self.b2:
               
self.p = max(0, self.p - max(len(self.b1)/len(self.b2) , 1))
               
self.replace(args)
               
self.b2.remove(args)
               
self.t2.appendleft(args)
               
#print "%s:: t1:%s b1:%s t2:%s b2:%s p:%s" % (
               
#   repr(func)[10:30], len(self.t1),len(self.b1),len(self.t2),
               
#   len(self.b2), self.p)
               
return result
           
if len(self.t1) + len(self.b1) == self.c:
               
if len(self.t1) < self.c:
                   
self.b1.pop()
                   
self.replace(args)
               
else:
                   
del(self.cached[self.t1.pop()])
           
else:
                total
= len(self.t1) + len(self.b1) + len(
                   
self.t2) + len(self.b2)
               
if total >= self.c:
                   
if total == (2 * self.c):
                       
self.b2.pop()
                   
self.replace(args)
           
self.t1.appendleft(args)
           
return result
       
return wrapper

History