|
1 | 1 | import weakref |
| 2 | +import threading |
2 | 3 |
|
3 | 4 | from django.dispatch import saferef |
4 | 5 |
|
@@ -30,6 +31,7 @@ def __init__(self, providing_args=None): |
30 | 31 | if providing_args is None: |
31 | 32 | providing_args = [] |
32 | 33 | self.providing_args = set(providing_args) |
| 34 | + self.lock = threading.Lock() |
33 | 35 |
|
34 | 36 | def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): |
35 | 37 | """ |
@@ -97,11 +99,15 @@ def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): |
97 | 99 | if weak: |
98 | 100 | receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver) |
99 | 101 |
|
100 | | - for r_key, _ in self.receivers: |
101 | | - if r_key == lookup_key: |
102 | | - break |
103 | | - else: |
104 | | - self.receivers.append((lookup_key, receiver)) |
| 102 | + try: |
| 103 | + self.lock.acquire() |
| 104 | + for r_key, _ in self.receivers: |
| 105 | + if r_key == lookup_key: |
| 106 | + break |
| 107 | + else: |
| 108 | + self.receivers.append((lookup_key, receiver)) |
| 109 | + finally: |
| 110 | + self.lock.release() |
105 | 111 |
|
106 | 112 | def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None): |
107 | 113 | """ |
@@ -130,11 +136,15 @@ def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None): |
130 | 136 | else: |
131 | 137 | lookup_key = (_make_id(receiver), _make_id(sender)) |
132 | 138 |
|
133 | | - for index in xrange(len(self.receivers)): |
134 | | - (r_key, _) = self.receivers[index] |
135 | | - if r_key == lookup_key: |
136 | | - del self.receivers[index] |
137 | | - break |
| 139 | + try: |
| 140 | + self.lock.acquire() |
| 141 | + for index in xrange(len(self.receivers)): |
| 142 | + (r_key, _) = self.receivers[index] |
| 143 | + if r_key == lookup_key: |
| 144 | + del self.receivers[index] |
| 145 | + break |
| 146 | + finally: |
| 147 | + self.lock.release() |
138 | 148 |
|
139 | 149 | def send(self, sender, **named): |
140 | 150 | """ |
@@ -227,14 +237,21 @@ def _remove_receiver(self, receiver): |
227 | 237 | Remove dead receivers from connections. |
228 | 238 | """ |
229 | 239 |
|
230 | | - to_remove = [] |
231 | | - for key, connected_receiver in self.receivers: |
232 | | - if connected_receiver == receiver: |
233 | | - to_remove.append(key) |
234 | | - for key in to_remove: |
235 | | - for idx, (r_key, _) in enumerate(self.receivers): |
236 | | - if r_key == key: |
237 | | - del self.receivers[idx] |
| 240 | + try: |
| 241 | + self.lock.acquire() |
| 242 | + to_remove = [] |
| 243 | + for key, connected_receiver in self.receivers: |
| 244 | + if connected_receiver == receiver: |
| 245 | + to_remove.append(key) |
| 246 | + for key in to_remove: |
| 247 | + last_idx = len(self.receivers) - 1 |
| 248 | + # enumerate in reverse order so that indexes are valid even |
| 249 | + # after we delete some items |
| 250 | + for idx, (r_key, _) in enumerate(reversed(self.receivers)): |
| 251 | + if r_key == key: |
| 252 | + del self.receivers[last_idx-idx] |
| 253 | + finally: |
| 254 | + self.lock.release() |
238 | 255 |
|
239 | 256 |
|
240 | 257 | def receiver(signal, **kwargs): |
|
0 commit comments