@@ -948,6 +948,17 @@ def f(cls, cond, sleeping, woken, timeout=None):
948948 woken .release ()
949949 cond .release ()
950950
951+ def assertReachesEventually (self , func , value ):
952+ for i in range (10 ):
953+ try :
954+ if func () == value :
955+ break
956+ except NotImplementedError :
957+ break
958+ time .sleep (DELTA )
959+ time .sleep (DELTA )
960+ self .assertReturnsIfImplemented (value , func )
961+
951962 def check_invariant (self , cond ):
952963 # this is only supposed to succeed when there are no sleepers
953964 if self .TYPE == 'processes' :
@@ -1055,13 +1066,54 @@ def test_notify_all(self):
10551066 cond .release ()
10561067
10571068 # check they have all woken
1058- for i in range (10 ):
1059- try :
1060- if get_value (woken ) == 6 :
1061- break
1062- except NotImplementedError :
1063- break
1064- time .sleep (DELTA )
1069+ self .assertReachesEventually (lambda : get_value (woken ), 6 )
1070+
1071+ # check state is not mucked up
1072+ self .check_invariant (cond )
1073+
1074+ def test_notify_n (self ):
1075+ cond = self .Condition ()
1076+ sleeping = self .Semaphore (0 )
1077+ woken = self .Semaphore (0 )
1078+
1079+ # start some threads/processes
1080+ for i in range (3 ):
1081+ p = self .Process (target = self .f , args = (cond , sleeping , woken ))
1082+ p .daemon = True
1083+ p .start ()
1084+
1085+ t = threading .Thread (target = self .f , args = (cond , sleeping , woken ))
1086+ t .daemon = True
1087+ t .start ()
1088+
1089+ # wait for them to all sleep
1090+ for i in range (6 ):
1091+ sleeping .acquire ()
1092+
1093+ # check no process/thread has woken up
1094+ time .sleep (DELTA )
1095+ self .assertReturnsIfImplemented (0 , get_value , woken )
1096+
1097+ # wake some of them up
1098+ cond .acquire ()
1099+ cond .notify (n = 2 )
1100+ cond .release ()
1101+
1102+ # check 2 have woken
1103+ self .assertReachesEventually (lambda : get_value (woken ), 2 )
1104+
1105+ # wake the rest of them
1106+ cond .acquire ()
1107+ cond .notify (n = 4 )
1108+ cond .release ()
1109+
1110+ self .assertReachesEventually (lambda : get_value (woken ), 6 )
1111+
1112+ # doesn't do anything more
1113+ cond .acquire ()
1114+ cond .notify (n = 3 )
1115+ cond .release ()
1116+
10651117 self .assertReturnsIfImplemented (6 , get_value , woken )
10661118
10671119 # check state is not mucked up
0 commit comments