Skip to content

Commit

Permalink
[1.2.X] Make django signals more thread-safe. Thanks milosu for the p…
Browse files Browse the repository at this point in the history
…atch!

Backport of r14662 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@14663 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
honzakral committed Nov 21, 2010
1 parent 4d7525c commit 99bad1b
Showing 1 changed file with 37 additions and 18 deletions.
55 changes: 37 additions & 18 deletions django/dispatch/dispatcher.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import weakref
import threading

from django.dispatch import saferef

Expand Down Expand Up @@ -30,6 +31,7 @@ def __init__(self, providing_args=None):
if providing_args is None:
providing_args = []
self.providing_args = set(providing_args)
self.lock = threading.Lock()

def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
"""
Expand Down Expand Up @@ -97,11 +99,15 @@ def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
if weak:
receiver = saferef.safeRef(receiver, onDelete=self._remove_receiver)

for r_key, _ in self.receivers:
if r_key == lookup_key:
break
else:
self.receivers.append((lookup_key, receiver))
try:
self.lock.acquire()
for r_key, _ in self.receivers:
if r_key == lookup_key:
break
else:
self.receivers.append((lookup_key, receiver))
finally:
self.lock.release()

def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None):
"""
Expand Down Expand Up @@ -130,11 +136,15 @@ def disconnect(self, receiver=None, sender=None, weak=True, dispatch_uid=None):
else:
lookup_key = (_make_id(receiver), _make_id(sender))

for index in xrange(len(self.receivers)):
(r_key, _) = self.receivers[index]
if r_key == lookup_key:
del self.receivers[index]
break
try:
self.lock.acquire()
for index in xrange(len(self.receivers)):
(r_key, _) = self.receivers[index]
if r_key == lookup_key:
del self.receivers[index]
break
finally:
self.lock.release()

def send(self, sender, **named):
"""
Expand Down Expand Up @@ -227,11 +237,20 @@ def _remove_receiver(self, receiver):
Remove dead receivers from connections.
"""

to_remove = []
for key, connected_receiver in self.receivers:
if connected_receiver == receiver:
to_remove.append(key)
for key in to_remove:
for idx, (r_key, _) in enumerate(self.receivers):
if r_key == key:
del self.receivers[idx]
try:
self.lock.acquire()
to_remove = []
for key, connected_receiver in self.receivers:
if connected_receiver == receiver:
to_remove.append(key)
for key in to_remove:
last_idx = len(self.receivers) - 1
# enumerate in reverse order so that indexes are valid even
# after we delete some items
for idx, (r_key, _) in enumerate(reversed(self.receivers)):
if r_key == key:
del self.receivers[last_idx-idx]
finally:
self.lock.release()


0 comments on commit 99bad1b

Please sign in to comment.