From 5543b2a9cc7381931431c69d93a77ba5d5d58e2e Mon Sep 17 00:00:00 2001 From: Ned Konz Date: Wed, 1 Sep 2021 10:48:15 -0700 Subject: [PATCH] extmod/uasyncio: Add clear method to ThreadSafeFlag. This is useful in situations where the ThreadSafeFlag is reused and needs to be cleared of any previous, unwanted event. For example, clear the flag at the start of an operation, trigger the operation (eg an I2C write), then (a)wait for an external event to set the flag (eg a pin IRQ). Further events may trigger the flag again but these are unwanted and should be cleared before the next cycle starts. --- docs/library/uasyncio.rst | 7 ++++++- extmod/uasyncio/event.py | 5 ++++- tests/extmod/uasyncio_threadsafeflag.py | 20 ++++++++++++++++++++ tests/extmod/uasyncio_threadsafeflag.py.exp | 11 +++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/docs/library/uasyncio.rst b/docs/library/uasyncio.rst index 0abbf8dd8d..859d505d79 100644 --- a/docs/library/uasyncio.rst +++ b/docs/library/uasyncio.rst @@ -153,9 +153,14 @@ class ThreadSafeFlag .. method:: ThreadSafeFlag.set() - Set the flag. If there is a task waiting on the event, it will be scheduled + Set the flag. If there is a task waiting on the flag, it will be scheduled to run. +.. method:: ThreadSafeFlag.clear() + + Clear the flag. This may be used to ensure that a possibly previously-set + flag is clear before waiting for it. + .. method:: ThreadSafeFlag.wait() Wait for the flag to be set. If the flag is already set then it returns diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py index c48904b983..654ccefa98 100644 --- a/extmod/uasyncio/event.py +++ b/extmod/uasyncio/event.py @@ -36,7 +36,7 @@ class Event: # MicroPython-extension: This can be set from outside the asyncio event loop, # such as other threads, IRQs or scheduler context. Implementation is a stream # that asyncio will poll until a flag is set. -# Note: Unlike Event, this is self-clearing. +# Note: Unlike Event, this is self-clearing after a wait(). try: import uio @@ -52,6 +52,9 @@ try: def set(self): self._flag = 1 + def clear(self): + self._flag = 0 + async def wait(self): if not self._flag: yield core._io_queue.queue_read(self) diff --git a/tests/extmod/uasyncio_threadsafeflag.py b/tests/extmod/uasyncio_threadsafeflag.py index 4e002a3d2a..a8a08d2e92 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py +++ b/tests/extmod/uasyncio_threadsafeflag.py @@ -75,5 +75,25 @@ async def main(): print("wait task") await t + # Flag set, cleared, and set again. + print("----") + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("clear event") + flag.clear() + print("yield") + await asyncio.sleep(0) + t = asyncio.create_task(task(4, flag)) + print("yield") + await asyncio.sleep(0) + print("set event") + flag.set() + print("yield") + await asyncio.sleep(0) + print("wait task") + await t + asyncio.run(main()) diff --git a/tests/extmod/uasyncio_threadsafeflag.py.exp b/tests/extmod/uasyncio_threadsafeflag.py.exp index aef4e479ba..757115ac4b 100644 --- a/tests/extmod/uasyncio_threadsafeflag.py.exp +++ b/tests/extmod/uasyncio_threadsafeflag.py.exp @@ -19,3 +19,14 @@ yield task 3 task 3 done wait task +---- +set event +yield +clear event +yield +yield +task 4 +set event +yield +wait task +task 4 done