Skip to content

Commit 00b486f

Browse files
committed
Fix bug in barrier nowait. asyntest.py now prints expected output.
1 parent 9af4f64 commit 00b486f

File tree

3 files changed

+121
-9
lines changed

3 files changed

+121
-9
lines changed

PRIMITIVES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ is raised.
199199

200200
## 3.6 ExitGate
201201

202+
This is obsolescent. It is a nasty hack which will be redundant once these PR's
203+
which provide task cancellation have been merged: firmware PR #3380 and
204+
micropython-lib PR #221.
205+
202206
The uasyncio library lacks a mechanism for preventing a coroutine from being
203207
rescheduled; the only way for a coro to be removed from the queue is for it to
204208
run to completion. The ``ExitGate`` class provides a means whereby a coro can

asyn.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,11 @@ def __await__(self):
133133
self._nowait = False
134134
if self._func is not None:
135135
launch(self._func, self._args)
136-
self._reset(not self._down)
136+
self._reset(not self._down) # Toggle direction to release others
137137
return
138138

139-
if self._nowait:
139+
if self._nowait: # Updated count, not at limit, so all done
140140
self._nowait = False
141-
if self._func is not None:
142-
launch(self._func, self._args)
143141
return
144142

145143
direction = self._down
@@ -158,7 +156,7 @@ def _reset(self, down):
158156
self._down = down
159157
self._count = self._participants if down else 0
160158

161-
def _at_limit(self):
159+
def _at_limit(self): # Has count reached up or down limit?
162160
limit = 0 if self._down else self._participants
163161
return self._count == limit
164162

asyntest.py

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020

2121
from asyn import Lock, Event, Semaphore, BoundedSemaphore, Barrier, Cancellable, CancelError
2222

23+
def printexp(exp, runtime=0):
24+
print('Expected output:')
25+
print('\x1b[32m')
26+
print(exp)
27+
print('\x1b[39m')
28+
if runtime:
29+
print('Running (runtime = {}s):'.format(runtime))
30+
else:
31+
print('Running (runtime < 1s):')
32+
2333
# ************ Test Event class ************
2434
# Demo use of acknowledge event
2535

@@ -52,10 +62,30 @@ async def run_ack():
5262

5363
async def ack_coro(delay):
5464
await asyncio.sleep(delay)
55-
print("I've seen starships burn off the shoulder of Orion...")
65+
print("I've seen attack ships burn on the shoulder of Orion...")
5666
print("Time to die...")
5767

5868
def ack_test():
69+
printexp('''event was set
70+
Eventwait 1 got event with value 0
71+
Eventwait 2 got event with value 0
72+
Cleared ack1
73+
Cleared ack2
74+
Cleared event
75+
event was set
76+
Eventwait 1 got event with value 1
77+
Eventwait 2 got event with value 1
78+
79+
... text omitted ...
80+
81+
Eventwait 1 got event with value 9
82+
Eventwait 2 got event with value 9
83+
Cleared ack1
84+
Cleared ack2
85+
Cleared event
86+
I've seen attack ships burn on the shoulder of Orion...
87+
Time to die...
88+
''', 10)
5989
loop = asyncio.get_event_loop()
6090
loop.create_task(run_ack())
6191
loop.run_until_complete(ack_coro(10))
@@ -98,6 +128,26 @@ async def run_event_test(lp):
98128
print('Tasks complete')
99129

100130
def event_test(lp=True): # Option to use low priority scheduling
131+
printexp('''Test Lock class
132+
Test Event class
133+
got here
134+
gh1
135+
waiting for event
136+
run_lock 1 waiting for lock
137+
run_lock 1 acquired lock
138+
run_lock 2 waiting for lock
139+
run_lock 3 waiting for lock
140+
Waiting 5 secs before setting event
141+
run_lock 3 acquired lock
142+
run_lock 1 released lock
143+
run_lock 2 acquired lock
144+
run_lock 3 released lock
145+
run_lock 2 released lock
146+
event was set
147+
got event
148+
Event status OK
149+
Tasks complete
150+
''', 5)
101151
loop = asyncio.get_event_loop()
102152
loop.run_until_complete(run_event_test(lp))
103153

@@ -117,6 +167,12 @@ async def report():
117167
await barrier
118168

119169
def barrier_test():
170+
printexp('''0 0 0 Synch
171+
1 1 1 Synch
172+
2 2 2 Synch
173+
3 3 3 Synch
174+
4 4 4 Synch
175+
''')
120176
loop = asyncio.get_event_loop()
121177
for _ in range(3):
122178
loop.create_task(report())
@@ -150,6 +206,44 @@ async def run_sema_test(bounded):
150206
print('Bounded semaphore exception test OK')
151207

152208
def semaphore_test(bounded=False):
209+
if bounded:
210+
exp = '''run_sema 0 trying to access semaphore
211+
run_sema 0 acquired semaphore
212+
run_sema 1 trying to access semaphore
213+
run_sema 1 acquired semaphore
214+
run_sema 2 trying to access semaphore
215+
run_sema 2 acquired semaphore
216+
run_sema 3 trying to access semaphore
217+
run_sema 4 trying to access semaphore
218+
run_sema 3 acquired semaphore
219+
run_sema 0 has released semaphore
220+
run_sema 4 acquired semaphore
221+
run_sema 1 has released semaphore
222+
run_sema 2 has released semaphore
223+
run_sema 3 has released semaphore
224+
run_sema 4 has released semaphore
225+
Bounded semaphore exception test OK
226+
227+
Exact sequence of acquisition may vary when 3 and 4 compete for semaphore.'''
228+
else:
229+
exp = '''run_sema 0 trying to access semaphore
230+
run_sema 0 acquired semaphore
231+
run_sema 1 trying to access semaphore
232+
run_sema 1 acquired semaphore
233+
run_sema 2 trying to access semaphore
234+
run_sema 2 acquired semaphore
235+
run_sema 3 trying to access semaphore
236+
run_sema 4 trying to access semaphore
237+
run_sema 3 acquired semaphore
238+
run_sema 0 has released semaphore
239+
run_sema 4 acquired semaphore
240+
run_sema 1 has released semaphore
241+
run_sema 2 has released semaphore
242+
run_sema 3 has released semaphore
243+
run_sema 4 has released semaphore
244+
245+
Exact sequence of acquisition may vary when 3 and 4 compete for semaphore.'''
246+
printexp(exp, 3)
153247
loop = asyncio.get_event_loop()
154248
loop.run_until_complete(run_sema_test(bounded))
155249

@@ -184,6 +278,12 @@ async def run_cancel_test1():
184278
print(res)
185279

186280
def cancel_test1():
281+
printexp('''foo will be cancelled when next scheduled
282+
not_me was not cancellable.
283+
foo was cancelled.
284+
-1
285+
42
286+
''', 8)
187287
loop = asyncio.get_event_loop()
188288
loop.run_until_complete(run_cancel_test1())
189289

@@ -195,14 +295,14 @@ async def forever(n):
195295
await asyncio.sleep(7 + n)
196296
print('Running instance', n)
197297

198-
barrier = Barrier(3)
298+
barrier_cancel = Barrier(3)
199299

200300
# Cancellable coros must trap the CancelError
201301
async def rats(n):
202302
try:
203303
await forever(n)
204304
except CancelError:
205-
await barrier(nowait = True)
305+
await barrier_cancel(nowait = True)
206306
print('Instance', n, 'was cancelled')
207307

208308
async def run_cancel_test2():
@@ -214,9 +314,19 @@ async def run_cancel_test2():
214314
print('About to cancel tasks')
215315
Cancellable.cancel('rats_1')
216316
Cancellable.cancel('rats_2')
217-
await barrier
317+
await barrier_cancel
218318
print('tasks were cancelled')
219319

220320
def cancel_test2():
321+
printexp('''Running two tasks
322+
Started forever() instance 1
323+
Started forever() instance 2
324+
Running instance 1
325+
Running instance 2
326+
About to cancel tasks
327+
Instance 1 was cancelled
328+
Instance 2 was cancelled
329+
tasks were cancelled
330+
''', 20)
221331
loop = asyncio.get_event_loop()
222332
loop.run_until_complete(run_cancel_test2())

0 commit comments

Comments
 (0)