1 # urllib3/_collections.py
2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
4 # This module is part of urllib3 and is released under
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php
7 from collections import MutableMapping
9 from threading import RLock
10 except ImportError: # Platform-specific: No threads available
15 def __exit__(self, exc_type, exc_value, traceback):
20 from collections import OrderedDict
22 from .packages.ordered_dict import OrderedDict
25 __all__ = ['RecentlyUsedContainer']
31 class RecentlyUsedContainer(MutableMapping):
33 Provides a thread-safe dict-like container which maintains up to
34 ``maxsize`` keys while throwing away the least-recently-used keys beyond
38 Maximum number of recent elements to retain.
41 Every time an item is evicted from the container,
42 ``dispose_func(value)`` is called. Callback which will get called
45 ContainerCls = OrderedDict
47 def __init__(self, maxsize=10, dispose_func=None):
48 self._maxsize = maxsize
49 self.dispose_func = dispose_func
51 self._container = self.ContainerCls()
54 def __getitem__(self, key):
55 # Re-insert the item, moving it to the end of the eviction line.
57 item = self._container.pop(key)
58 self._container[key] = item
61 def __setitem__(self, key, value):
64 # Possibly evict the existing value of 'key'
65 evicted_value = self._container.get(key, _Null)
66 self._container[key] = value
68 # If we didn't evict an existing value, we might have to evict the
69 # least recently used item from the beginning of the container.
70 if len(self._container) > self._maxsize:
71 _key, evicted_value = self._container.popitem(last=False)
73 if self.dispose_func and evicted_value is not _Null:
74 self.dispose_func(evicted_value)
76 def __delitem__(self, key):
78 value = self._container.pop(key)
81 self.dispose_func(value)
85 return len(self._container)
88 raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.')
92 # Copy pointers to all values, then wipe the mapping
93 # under Python 2, this copies the list of values twice :-|
94 values = list(self._container.values())
95 self._container.clear()
99 self.dispose_func(value)
103 return self._container.keys()