Django

Code

Changeset 4588

Show
Ignore:
Timestamp:
02/25/07 21:17:04 (2 years ago)
Author:
jacob
Message:

Fixed #3439: vastly improved the performance of django.dispatch (and added tests!). Thanks to Brian Harring for the patch. Note that one of the new tests fails under sqlite currently; it's not clear if this is a sqlite problem or a problem with the tests, but it appears not to be a problem with the dispatcher itself.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/dispatch/dispatcher.py

    r4265 r4588  
    2626        vs. the original code.) 
    2727""" 
    28 from __future__ import generators 
    2928import types, weakref 
    3029from django.dispatch import saferef, robustapply, errors 
     
    3433__version__ = "$Revision: 1.9 $"[11:-2] 
    3534 
    36 try: 
    37     True 
    38 except NameError: 
    39     True = 1==1 
    40     False = 1==0 
    4135 
    4236class _Parameter: 
     
    141135        receiver = saferef.safeRef(receiver, onDelete=_removeReceiver) 
    142136    senderkey = id(sender) 
    143     if connections.has_key(senderkey): 
    144         signals = connections[senderkey] 
    145     else: 
    146         connections[senderkey] = signals = {} 
     137 
     138    signals = connections.setdefault(senderkey, {}) 
     139 
    147140    # Keep track of senders for cleanup. 
    148141    # Is Anonymous something we want to clean up? 
     
    252245    object. 
    253246    """ 
    254     try: 
    255         return connections[id(sender)][signal] 
    256     except KeyError: 
    257         return [] 
     247    existing = connections.get(id(sender)) 
     248    if existing is not None: 
     249        return existing.get(signal, []) 
     250    return [] 
    258251 
    259252def liveReceivers(receivers): 
     
    279272    """Get list of all receivers from global tables 
    280273 
    281     This gets all receivers which should receive 
     274    This gets all dereferenced receivers which should receive 
    282275    the given signal from sender, each receiver should 
    283276    be produced only once by the resulting generator 
    284277    """ 
    285278    receivers = {} 
    286     for set in ( 
    287         # Get receivers that receive *this* signal from *this* sender. 
    288         getReceivers( sender, signal ), 
    289         # Add receivers that receive *any* signal from *this* sender. 
    290         getReceivers( sender, Any ), 
    291         # Add receivers that receive *this* signal from *any* sender. 
    292         getReceivers( Any, signal ), 
    293         # Add receivers that receive *any* signal from *any* sender. 
    294         getReceivers( Any, Any ), 
    295     ): 
    296         for receiver in set: 
    297             if receiver: # filter out dead instance-method weakrefs 
    298                 try: 
    299                     if not receivers.has_key( receiver ): 
    300                         receivers[receiver] = 1 
    301                         yield receiver 
    302                 except TypeError: 
    303                     # dead weakrefs raise TypeError on hash... 
    304                     pass 
     279    # Get receivers that receive *this* signal from *this* sender. 
     280    # Add receivers that receive *any* signal from *this* sender. 
     281    # Add receivers that receive *this* signal from *any* sender. 
     282    # Add receivers that receive *any* signal from *any* sender. 
     283    l = [] 
     284    i = id(sender) 
     285    if i in connections: 
     286        sender_receivers = connections[i] 
     287        if signal in sender_receivers: 
     288            l.extend(sender_receivers[signal]) 
     289        if signal is not Any and Any in sender_receivers: 
     290            l.extend(sender_receivers[Any]) 
     291 
     292    if sender is not Any: 
     293        i = id(Any) 
     294        if i in connections: 
     295            sender_receivers = connections[i] 
     296            if sender_receivers is not None: 
     297                if signal in sender_receivers: 
     298                    l.extend(sender_receivers[signal]) 
     299                if signal is not Any and Any in sender_receivers: 
     300                    l.extend(sender_receivers[Any]) 
     301 
     302    for receiver in l: 
     303        try: 
     304            if not receiver in receivers: 
     305                if isinstance(receiver, WEAKREF_TYPES): 
     306                    receiver = receiver() 
     307                    # this should only (rough guess) be possible if somehow, deref'ing 
     308                    # triggered a wipe. 
     309                    if receiver is None: 
     310                        continue 
     311                receivers[receiver] = 1 
     312                yield receiver 
     313        except TypeError: 
     314            # dead weakrefs raise TypeError on hash... 
     315            pass 
    305316 
    306317def send(signal=Any, sender=Anonymous, *arguments, **named): 
     
    341352    # Return a list of tuple pairs [(receiver, response), ... ]. 
    342353    responses = [] 
    343     for receiver in liveReceivers(getAllReceivers(sender, signal)): 
     354    for receiver in getAllReceivers(sender, signal): 
    344355        response = robustapply.robustApply( 
    345356            receiver, 
     
    351362        responses.append((receiver, response)) 
    352363    return responses 
     364 
     365 
    353366def sendExact( signal=Any, sender=Anonymous, *arguments, **named ): 
    354367    """Send signal only to those receivers registered for exact message 
     
    422435    """Remove senderkey from connections.""" 
    423436    _removeBackrefs(senderkey) 
    424     try: 
    425         del connections[senderkey] 
    426     except KeyError: 
    427         pass 
    428     # Senderkey will only be in senders dictionary if sender  
    429     # could be weakly referenced. 
    430     try:  
    431         del senders[senderkey] 
    432     except:  
    433         pass 
     437 
     438    connections.pop(senderkey, None) 
     439    senders.pop(senderkey, None) 
    434440 
    435441 
    436442def _removeBackrefs( senderkey): 
    437443    """Remove all back-references to this senderkey""" 
    438     try: 
    439         signals = connections[senderkey] 
    440     except KeyError: 
    441         signals = None 
    442     else: 
    443         items = signals.items() 
    444         def allReceivers( ): 
    445             for signal,set in items: 
    446                 for item in set: 
    447                     yield item 
    448         for receiver in allReceivers(): 
     444    for receiver_list in connections.pop(senderkey, {}).values(): 
     445        for receiver in receiver_list: 
    449446            _killBackref( receiver, senderkey ) 
     447 
    450448 
    451449def _removeOldBackRefs(senderkey, signal, receiver, receivers): 
     
    484482    """Do the actual removal of back reference from receiver to senderkey""" 
    485483    receiverkey = id(receiver) 
    486     set = sendersBack.get( receiverkey, () ) 
    487     while senderkey in set: 
     484    receivers_list = sendersBack.get( receiverkey, () ) 
     485    while senderkey in receivers_list: 
    488486        try: 
    489             set.remove( senderkey ) 
     487            receivers_list.remove( senderkey ) 
    490488        except: 
    491489            break 
    492     if not set: 
     490    if not receivers_list: 
    493491        try: 
    494492            del sendersBack[ receiverkey ]