<s> from collections import deque <EOL> from threading import RLock <EOL> __all__ = [ '<STR_LIT>' ] <EOL> class AccessEntry ( object ) : <EOL> __slots__ = ( '<STR_LIT:key>' , '<STR_LIT>' ) <EOL> def __init__ ( self , key , is_valid = True ) : <EOL> self . key = key <EOL> self . is_valid = is_valid <EOL> class RecentlyUsedContainer ( dict ) : <EOL> """<STR_LIT>""" <EOL> CLEANUP_FACTOR = <NUM_LIT:10> <EOL> def __init__ ( self , maxsize = <NUM_LIT:10> ) : <EOL> self . _maxsize = maxsize <EOL> self . _container = { } <EOL> self . access_log = deque ( ) <EOL> self . access_log_lock = RLock ( ) <EOL> self . access_lookup = { } <EOL> self . access_log_limit = maxsize * self . CLEANUP_FACTOR <EOL> def _invalidate_entry ( self , key ) : <EOL> "<STR_LIT>" <EOL> old_entry = self . access_lookup . get ( key ) <EOL> if old_entry : <EOL> old_entry . is_valid = False <EOL> return old_entry <EOL> def _push_entry ( self , key ) : <EOL> "<STR_LIT>" <EOL> self . _invalidate_entry ( key ) <EOL> new_entry = AccessEntry ( key ) <EOL> self . access_lookup [ key ] = new_entry <EOL> self . access_log_lock . acquire ( ) <EOL> self . access_log . appendleft ( new_entry ) <EOL> self . access_log_lock . release ( ) <EOL> def _prune_entries ( self , num ) : <EOL> "<STR_LIT>" <EOL> while num > <NUM_LIT:0> : <EOL> self . access_log_lock . acquire ( ) <EOL> p = self . access_log . pop ( ) <EOL> self . access_log_lock . release ( ) <EOL> if not p . is_valid : <EOL> continue <EOL> dict . pop ( self , p . key , None ) <EOL> self . access_lookup . pop ( p . key , None ) <EOL> num -= <NUM_LIT:1> <EOL> def _prune_invalidated_entries ( self ) : <EOL> "<STR_LIT>" <EOL> self . access_log_lock . acquire ( ) <EOL> self . access_log = deque ( e for e in self . access_log if e . is_valid ) <EOL> self . access_log_lock . release ( ) <EOL> def _get_ordered_access_keys ( self ) : <EOL> "<STR_LIT>" <EOL> self . access_log_lock . acquire ( ) <EOL> r = [ e . key for e in self . access_log if e . is_valid ] <EOL> self . access_log_lock . release ( ) <EOL> return r <EOL> def __getitem__ ( self , key ) : <EOL> item = dict . get ( self , key ) <EOL> if not item : <EOL> raise KeyError ( key ) <EOL> self . _push_entry ( key ) <EOL> if len ( self . access_log ) > self . access_log_limit : <EOL> self . _prune_invalidated_entries ( ) <EOL> return item <EOL> def __setitem__ ( self , key , item ) : <EOL> dict . __setitem__ ( self , key , item ) <EOL> self . _push_entry ( key ) <EOL> self . _prune_entries ( len ( self ) - self . _maxsize ) <EOL> def __delitem__ ( self , key ) : <EOL> self . _invalidate_entry ( key ) <EOL> self . access_lookup . pop ( key , None ) <EOL> dict . __delitem__ ( self , key ) <EOL> def get ( self , key , default = None ) : <EOL> try : <EOL> return self [ key ] <EOL> except KeyError : <EOL> return default </s>
