-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
extmod/uasyncio: Add ThreadSafeEvent. #6886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This new class is self-clearing, which is different to how |
extmod/uasyncio/event.py
Outdated
|
||
# MicroPython-extension: Event class that can be set from IRQs or scheduler context. | ||
# Implementation is a stream that asyncio will poll until a flag is set. | ||
class ThreadSafeEvent(io.IOBase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm... this now puts a requirement on all ports to have uio.IOBase
... is it worth guarding this code in hasattr(uio, 'IOBase')
?
extmod/uasyncio/event.py
Outdated
@@ -29,3 +33,24 @@ async def wait(self): | |||
core.cur_task.data = self.waiting | |||
yield | |||
return True | |||
|
|||
|
|||
_MP_STREAM_POLL = const(3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to eliminate the need for a from micropython import const
I'd say just remove this line and hard-code the value with a comment below
extmod/uasyncio/event.py
Outdated
self._flag = 0 | ||
|
||
def ioctl(self, req, flags): | ||
if req == _MP_STREAM_POLL: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be hard-coded as: if req == 3: # MP_STREAM_POLL
60d5f7c
to
965cbff
Compare
OK that all sounds very reasonable -- I've update it to ThreadSafeFlag and added docs and a basic test. I've kept it self-clearing because it's hard to avoid races otherwise. The test is a bit annoying because it can't run on Unix (see #6885), but I've run it on pyboard and on a unix build with extmod/uselect. |
5f4bd8b
to
e2eefd4
Compare
Updated to use |
async def wait(self): | ||
yield core._io_queue.queue_read(self) | ||
self._flag = 0 | ||
except ImportError: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2x blank lines needed here for black formatting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
e2eefd4
to
6d5f4c6
Compare
.. method:: ThreadSafeFlag.wait() | ||
|
||
Wait for the flag to be set. If the flag is already set then it returns | ||
immediately. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that doesn't match the implementation (returning immediately if set)... maybe the implementation should be changed so it does return immediately if self._flag
is set... that would make things more responsive at the risk of "starving" other things (but since Event.wait already behaves this way we know it's probably ok to return immediately)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I agree. I've updated the code to return immediately and added that to the test.
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>
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
6d5f4c6
to
51e0a39
Compare
yield | ||
task 3 | ||
wait task | ||
task 3 done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when I run this test on a PYBD-SF6 I get:
set event
yield
task 3
task 3 done
wait task
which makes more sense to me than this .exp file, that task 3 starts and is immediately finished
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
51e0a39
to
83d2305
Compare
Thanks! |
Very nice. I'll do some testing later. |
You can make an async-pin like this: class AsyncPin:
def __init__(self, pin, trigger):
self.pin = pin
self.flag = ThreadSafeFlag()
self.pin.irq(lambda pin: self.flag.set(), trigger, hard=True)
def wait_edge(self):
return self.flag.wait() Then call |
How does this fit with uevent plans? |
I still have uevent on the to-do list, it's just been blocked by cmake and other things (which are being cleared now). I hope that we can still offer the same |
Fix espressif run modes
This is a MicroPython-extension that allows for events to be set from IRQ (hard or soft) or scheduler context.
Works on the bare-metal ports (which use extmod/uselect). To use this on Unix requires PR #6885