diff options
author | Jim Mussared <jim.mussared@gmail.com> | 2021-02-12 14:14:07 +1100 |
---|---|---|
committer | Jim Mussared <jim.mussared@gmail.com> | 2021-02-16 16:35:37 +1100 |
commit | 5e96e89999cd3b922dbc1a6ed473b44c81db92f4 (patch) | |
tree | 2256b392729db5930be82776b2f390efa0580de6 /extmod/uasyncio | |
parent | 4c54012373e6546704f534d0de3e900704ae9d11 (diff) |
extmod/uasyncio: Add ThreadSafeFlag.
This is a MicroPython-extension that allows for code running in IRQ
(hard or soft) or scheduler context to sequence asyncio code.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Diffstat (limited to 'extmod/uasyncio')
-rw-r--r-- | extmod/uasyncio/__init__.py | 1 | ||||
-rw-r--r-- | extmod/uasyncio/event.py | 31 |
2 files changed, 32 insertions, 0 deletions
diff --git a/extmod/uasyncio/__init__.py b/extmod/uasyncio/__init__.py index 08f924cf2..fa64438f6 100644 --- a/extmod/uasyncio/__init__.py +++ b/extmod/uasyncio/__init__.py @@ -10,6 +10,7 @@ _attrs = { "wait_for_ms": "funcs", "gather": "funcs", "Event": "event", + "ThreadSafeFlag": "event", "Lock": "lock", "open_connection": "stream", "start_server": "stream", diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py index 31cb00e05..c28ad1fb3 100644 --- a/extmod/uasyncio/event.py +++ b/extmod/uasyncio/event.py @@ -14,6 +14,8 @@ class Event: def set(self): # Event becomes set, schedule any tasks waiting on it + # Note: This must not be called from anything except the thread running + # the asyncio loop (i.e. neither hard or soft IRQ, or a different thread). while self.waiting.peek(): core._task_queue.push_head(self.waiting.pop_head()) self.state = True @@ -29,3 +31,32 @@ class Event: core.cur_task.data = self.waiting yield return True + + +# 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. +try: + import uio + + class ThreadSafeFlag(uio.IOBase): + def __init__(self): + self._flag = 0 + + def ioctl(self, req, flags): + if req == 3: # MP_STREAM_POLL + return self._flag * flags + return None + + def set(self): + self._flag = 1 + + async def wait(self): + if not self._flag: + yield core._io_queue.queue_read(self) + self._flag = 0 + + +except ImportError: + pass |