uasyncio.ThreadSafeFlag: is this use valid? #9972
Replies: 2 comments 7 replies
-
This looks like a neat solution! I don't see a problem with it. Conceptually it's very similar to how TSF is used in aioble, for example to queue writes on characteristics.
What should/could have been written this way? I see this TSE as being a very useful complement to TSF and E, but I think TSF is still useful on its own. For one thing it is very light weight and doesn't have the overhead of a task. Perhaps we should consider adding this TSE to asyncio too? I still wish we'd put TSF in a different module though... Btw, when we support awaiting hardware events (e.g. pin edges) should we allow multiple waiters on one pin? (I don't think this would work with the current proposal) |
Beta Was this translation helpful? Give feedback.
-
The reason TSF is the way it is, is so that it does not allocate any memory and That said, it should be possible to implement a TSE without the overhead of an additional task. Something like this: import uasyncio as asyncio
from pyb import Timer
class ThreadSafeEvent(asyncio.Event):
def __init__(self):
super().__init__()
self._waiting_on_tsf = False
self._tsf = asyncio.ThreadSafeFlag()
def set(self):
self._tsf.set()
async def wait(self):
if self._waiting_on_tsf == False:
self._waiting_on_tsf = True
await self._tsf.wait()
super().set()
self._waiting_on_tsf = False
else:
await super().wait()
# Test/demo
async def waiter(n, evt):
await evt.wait()
print(f"Waiter {n} got event")
async def main():
evt = ThreadSafeEvent()
tim = pyb.Timer(4, freq=1, callback=lambda t: evt.set())
while True:
tasks = [asyncio.create_task(waiter(n + 1, evt)) for n in range(4)]
await asyncio.gather(*tasks)
evt.clear()
print("Cleared event")
asyncio.run(main()) In the above, the first task to wait on the TSE will wait on the TSF. Subsequent tasks will wait on the Event. Then when the first one wakes up, it wakes the rest. I think there might be a problem though if the first task is cancelled while waiting, then the remaining tasks stay waiting forever. That may or may not be easy to fix with a try-finally. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
The
ThreadSafeFlag
has a limitation compared toEvent
in that it is self-clearing, so only one task may wait on it. This would appear to have a simple solution, which is to create a task which waits on the TSF and triggers anEvent
. I have used this, and it cropped up again here. The technique seems to work, and I can't see a flaw.I have a nagging doubt that if it was this easy, @dpgeorge would have written it this way. What is the view of this:
Beta Was this translation helpful? Give feedback.
All reactions