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 |