| OLD | NEW |
| 1 # urllib3/_collections.py | 1 # urllib3/_collections.py |
| 2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) | 2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) |
| 3 # | 3 # |
| 4 # This module is part of urllib3 and is released under | 4 # This module is part of urllib3 and is released under |
| 5 # the MIT License: http://www.opensource.org/licenses/mit-license.php | 5 # the MIT License: http://www.opensource.org/licenses/mit-license.php |
| 6 | 6 |
| 7 from collections import MutableMapping | 7 from collections import MutableMapping |
| 8 from threading import Lock | 8 from threading import RLock |
| 9 | 9 |
| 10 try: # Python 2.7+ | 10 try: # Python 2.7+ |
| 11 from collections import OrderedDict | 11 from collections import OrderedDict |
| 12 except ImportError: | 12 except ImportError: |
| 13 from .packages.ordered_dict import OrderedDict | 13 from .packages.ordered_dict import OrderedDict |
| 14 | 14 |
| 15 | 15 |
| 16 __all__ = ['RecentlyUsedContainer'] | 16 __all__ = ['RecentlyUsedContainer'] |
| 17 | 17 |
| 18 | 18 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 33 ``dispose_func(value)`` is called. Callback which will get called | 33 ``dispose_func(value)`` is called. Callback which will get called |
| 34 """ | 34 """ |
| 35 | 35 |
| 36 ContainerCls = OrderedDict | 36 ContainerCls = OrderedDict |
| 37 | 37 |
| 38 def __init__(self, maxsize=10, dispose_func=None): | 38 def __init__(self, maxsize=10, dispose_func=None): |
| 39 self._maxsize = maxsize | 39 self._maxsize = maxsize |
| 40 self.dispose_func = dispose_func | 40 self.dispose_func = dispose_func |
| 41 | 41 |
| 42 self._container = self.ContainerCls() | 42 self._container = self.ContainerCls() |
| 43 self._lock = Lock() | 43 self.lock = RLock() |
| 44 | 44 |
| 45 def __getitem__(self, key): | 45 def __getitem__(self, key): |
| 46 # Re-insert the item, moving it to the end of the eviction line. | 46 # Re-insert the item, moving it to the end of the eviction line. |
| 47 with self._lock: | 47 with self.lock: |
| 48 item = self._container.pop(key) | 48 item = self._container.pop(key) |
| 49 self._container[key] = item | 49 self._container[key] = item |
| 50 return item | 50 return item |
| 51 | 51 |
| 52 def __setitem__(self, key, value): | 52 def __setitem__(self, key, value): |
| 53 evicted_value = _Null | 53 evicted_value = _Null |
| 54 with self._lock: | 54 with self.lock: |
| 55 # Possibly evict the existing value of 'key' | 55 # Possibly evict the existing value of 'key' |
| 56 evicted_value = self._container.get(key, _Null) | 56 evicted_value = self._container.get(key, _Null) |
| 57 self._container[key] = value | 57 self._container[key] = value |
| 58 | 58 |
| 59 # If we didn't evict an existing value, we might have to evict the | 59 # If we didn't evict an existing value, we might have to evict the |
| 60 # least recently used item from the beginning of the container. | 60 # least recently used item from the beginning of the container. |
| 61 if len(self._container) > self._maxsize: | 61 if len(self._container) > self._maxsize: |
| 62 _key, evicted_value = self._container.popitem(last=False) | 62 _key, evicted_value = self._container.popitem(last=False) |
| 63 | 63 |
| 64 if self.dispose_func and evicted_value is not _Null: | 64 if self.dispose_func and evicted_value is not _Null: |
| 65 self.dispose_func(evicted_value) | 65 self.dispose_func(evicted_value) |
| 66 | 66 |
| 67 def __delitem__(self, key): | 67 def __delitem__(self, key): |
| 68 with self._lock: | 68 with self.lock: |
| 69 value = self._container.pop(key) | 69 value = self._container.pop(key) |
| 70 | 70 |
| 71 if self.dispose_func: | 71 if self.dispose_func: |
| 72 self.dispose_func(value) | 72 self.dispose_func(value) |
| 73 | 73 |
| 74 def __len__(self): | 74 def __len__(self): |
| 75 with self._lock: | 75 with self.lock: |
| 76 return len(self._container) | 76 return len(self._container) |
| 77 | 77 |
| 78 def __iter__(self): | 78 def __iter__(self): |
| 79 raise NotImplementedError('Iteration over this class is unlikely to be t
hreadsafe.') | 79 raise NotImplementedError('Iteration over this class is unlikely to be t
hreadsafe.') |
| 80 | 80 |
| 81 def clear(self): | 81 def clear(self): |
| 82 with self._lock: | 82 with self.lock: |
| 83 # Copy pointers to all values, then wipe the mapping | 83 # Copy pointers to all values, then wipe the mapping |
| 84 # under Python 2, this copies the list of values twice :-| | 84 # under Python 2, this copies the list of values twice :-| |
| 85 values = list(self._container.values()) | 85 values = list(self._container.values()) |
| 86 self._container.clear() | 86 self._container.clear() |
| 87 | 87 |
| 88 if self.dispose_func: | 88 if self.dispose_func: |
| 89 for value in values: | 89 for value in values: |
| 90 self.dispose_func(value) | 90 self.dispose_func(value) |
| 91 | 91 |
| 92 def keys(self): | 92 def keys(self): |
| 93 with self._lock: | 93 with self.lock: |
| 94 return self._container.keys() | 94 return self._container.keys() |
| OLD | NEW |