@@ -33,23 +33,16 @@ def __init__ (self, IO):
3333 messages, e.g. bencode.BencodeIO."""
3434 self ._IO = IO
3535 self ._watches = {}
36+ self ._watches_lock = threading .RLock ()
3637 class Monitor (threading .Thread ):
3738 def run (_ ):
39+ watches = None
3840 for incoming in self ._IO :
39- # Dirty hack so we can iterate over the list.
40- # RuntimeError: dictionary changed size during iteration (Python3)
41- # So we just force out an iteration, even tho we get errors.
42- # Better approach is wanted, but all tests are passing, so yeah.
43- while True :
44- try :
45- for key , (pred , callback ) in self ._watches .items ():
46- if pred (incoming ):
47- callback (incoming , self , key )
48- except RuntimeError as e :
49- pass
50- finally :
51- break
52-
41+ with self ._watches_lock :
42+ watches = dict (self ._watches )
43+ for key , (pred , callback ) in self ._watches .items ():
44+ if pred (incoming ):
45+ callback (incoming , self , key )
5346 self ._thread = Monitor ()
5447 self ._thread .daemon = True
5548 self ._thread .start ()
@@ -63,7 +56,8 @@ def send (self, message):
6356
6457 def unwatch (self , key ):
6558 "Removes the watch previously registered with [key]."
66- self ._watches .pop (key , None )
59+ with self ._watches_lock :
60+ self ._watches .pop (key , None )
6761
6862 def watch (self , key , criteria , callback ):
6963 """Registers a new watch under [key] (which can be used with `unwatch()`
@@ -77,7 +71,8 @@ def watch (self, key, criteria, callback):
7771 pred = criteria
7872 else :
7973 pred = lambda incoming : _match_criteria (criteria , incoming )
80- self ._watches [key ] = (pred , callback )
74+ with self ._watches_lock :
75+ self ._watches [key ] = (pred , callback )
8176
8277# others can add in implementations here
8378_connect_fns = {"nrepl" : _bencode_connect }
0 commit comments