summaryrefslogtreecommitdiff
path: root/extmod/uasyncio
diff options
context:
space:
mode:
authorJim Mussared <jim.mussared@gmail.com>2021-02-12 14:14:07 +1100
committerJim Mussared <jim.mussared@gmail.com>2021-02-16 16:35:37 +1100
commit5e96e89999cd3b922dbc1a6ed473b44c81db92f4 (patch)
tree2256b392729db5930be82776b2f390efa0580de6 /extmod/uasyncio
parent4c54012373e6546704f534d0de3e900704ae9d11 (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__.py1
-rw-r--r--extmod/uasyncio/event.py31
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