bbcmicrobit / bbcmicrobit/micropython
Consider some form of event handling execution model
- Dominant language
- C
- Stars
- 646
- Forks
- 290
- PR merge metrics
- No merged PRs in 30d
Description
The excution model for uPy on the microbit is currently a single thread executing with full control. There are idle and system "threads" behind the scenes, but these are used to update low-level things like the display and are not exposed to the Python API (except as background animations).
TD has event handlers for things like button presses, and there have been requests for such things in uPy. Eg:
``` python
def click_handler():
print("you clicked the button!")
button_a.onclick(click_handler)
```
A "click" is defined as a short press down and release of the button. It's not easy to write a polling loop to detect a click event, and even more difficult to do other things while checking for such a click (basically you need to write your own cooperative scheduler).
There are a few ways I can think to make the above code work. They vary significantly in complexity and use.
**Simple events**
Queue events in the background and expose them using simple methods. Eg: `button_a.was_clicked()` -- this will check to see if the button was clicked since the last time this function was called. If it was then it returns True and resets the event state. Otherwise it returns False. In this case there are no event handlers, it's really just polling (but polling for button events, not simple button status).
**Explicit event handler**
Allow event handlers to be registered but force the user to periodically execute an "event check and handle" function. Eg:
``` python
def click_handler():
print("you clicked the button!")
button_a.onclick(click_handler)
while True:
microbit.event_handler() # check for pending events and execute the handlers if needed
# do other stuff
```
This is cooperative "multitasking". It makes the user aware that they need to do something special to get the event handlers to run, and gives control to the user when such callbacks are executed.
**Interrupt-like handler**
Allow event handlers to be registered and execute them like an interrupt (or Linux signal): when the event fires a short time later the main thread is paused and execution is passed to the relevant event handler. Only when the event handler is finished does execution return to the main thread. (The event handler would execute on the same stack as the main thread and no task switching is needed.)
This leads to less problems with data locking and deadlocks, but does expose a degree of preemptive issues to the kids. Eg an event handler can modify a list that you are currently iterating through.
Technically this scheme would be implemented by the VM periodically checking for pending events and pausing the current bytecode when an event comes up. That means event handling can't preempt a C/C++ function, but I think that's a good thing (keeps things simpler) and don't think it'll be a problem since all C/C++ functions eventually return (except panic!).
**Full monty**
Have actual threads that execute concurrently. This is way too complex (for the kids, and for us to implement), and I don't think we even need the power/flexibility that this offers.
Please raise your opinion on this very interesting topic!
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.