<div dir="ltr"><div><div><div><div><div>Perhaps you can add a check for a simple boolean 'stop' flag to your condition check, and when you want to stop the loop you set that flag and then call notify() on the condition. Then you can follow the standard condition variable protocol instead of all this nonsense. :-)<br><br>class Foo:<br>
async def some_method(self):<br>
self.uptodate = asyncio.Condition()<br>
self.stopped = False<br>
…<br>
await self.uptodate.acquire()<br>
try:<br>
while (not self.stopped) and self.some_condition():<br></div> await self.uptodate.wait()<br></div> finally:<br>
self.uptodate.release()<br></div> def stop_it(self):<br></div> self.stopped = True<br></div> self.uptodate.notify()<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 19, 2015 at 7:43 AM, Matthias Urlichs <span dir="ltr"><<a href="mailto:matthias@urlichs.de" target="_blank">matthias@urlichs.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The following code has a problem: the generator returned by .wait() has a<br>
finally: section. When self.stopped is set, it still needs to run. As it is<br>
asynchronous (it needs to re-acquire the lock), I need to come up with a<br>
reliable way to wait for it. If I don't, .release() will throw an exception<br>
because the lock is still unlocked.<br>
<br>
The best method to do this that I've come up with is the five marked lines.<br>
I keep thinking there must be a better way to do this (taking into account<br>
that I have no idea whether the 'await r' part of this is even necessary).<br>
<br>
<br>
```<br>
class StopMe(BaseException):<br>
pass<br>
class Foo:<br>
async dev some_method(self):<br>
self.uptodate = asyncio.Condition()<br>
self.stopped = asyncio.Future()<br>
…<br>
await self.uptodate.acquire()<br>
try:<br>
while self.some_condition():<br>
w = self.uptodate.wait()<br>
await asyncio.wait([w,self.stopped], loop=self.conn._loop,<br>
return_when=asyncio.FIRST_COMPLETED)<br>
with contextlib.suppress(StopMe): # FIXME?<br>
r = w.throw(StopMe()) # FIXME?<br>
if r is not None: # FIXME?<br>
await r # FIXME?<br>
await w # FIXME?<br>
finally:<br>
self.uptodate.release()<br>
```<br>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/guido%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/guido%40python.org</a><br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature">--Guido van Rossum (<a href="http://python.org/~guido" target="_blank">python.org/~guido</a>)</div>
</div>