Move bled112 to use deque instead of queue for packet handling
- Dominant language
- Python
- Stars
- 14
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
Right now we have a simple way for packets to be read from the BLED112. We have a dedicated thread that reads packets and puts them on a queue. The BLED112CommandProcessor runs in its own thread and blocks when it needs a packet on `queue.get()`. Packets are always processed one at a time.
For moving to asyncio, we need to instead give packets to `OperationManager` as input so that they can be used to unblock any running coroutine operations. `OperationManager.process_message()` must only be called from within the event loop itself, so we need an efficient way to hand packets from the `ReaderThread` to the event loop.
The obvious way would be to call `add_callback_threadsafe` for each packet but that means many locked callback adds as packet volumes increase. An alternative would be to batch packets with a timeout but that risks increasing latency when we are waiting for just 1 packet in and not many packets are coming.
An intermediate option is to share packets using an unlocked `deque` and have a handler scheduled that empties out the deque whenever it is run. A separate shared boolean flag notes if the handler has run since the last invocation so that the `ReaderThread` can avoid queuing it again since it will get all packets once it runs:

> **Important:** The ordering of setting `is_sched` is important to make sure there is no race condition where a packet could be added to the `deque` but no callback scheduled after that time. The logic has been thought through in the above diagram but not formally proven to be correct so it should be rechecked before implementation.
Contributor guide
Assessment
This issue has not been assessed yet.