bluerobotics / bluerobotics/ping-cpp
Reading from a UDP link busy-loops
- Ngôn ngữ chính
- C++
- Star
- 19
- Fork
- 17
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Mô tả
It would appear the API provides no way to structure read handling so it does not 100% saturate a CPU core while waiting for received messages. This was maybe tolerable when all messages were synchronous command responses, but with the new auto transmit function, my driver needs to just sit and wait for asynchronous receive data all of the time.
To start with, the provided test-device-ping360.cpp example uses `PingDevice::waitMessage()` to wait for auto data packets. Internally, `waitMessage()` calls `PingDevice::read()` in a tight loop until its timeout expires. There is a comment here that says `read()` blocks up to 0.1s, but this comment is a lie (at least for UDP, I didn't check the serial path). Inside `PingDevice::read()`, we just call the port `read()` method exactly once, and then attempt to parse any data returned from it. `UdpLink::read()` always returns immediately with whatever amount of data it was able to pull out of its buffer at that moment, so there is no blocking happening.
Even if the test case using `waitMessage()` didn't have this problem, I would ideally like to structure my driver such that I'm not continuously polling for new data. I tried setting things up with `AbstractLink::doOnReceived()` to let me know when data is available, so I could read until the available data was exhausted and handle any packets that were parsed in the process, but it turns out this is impossible with the given API. Since `PingDevice::read()` reads exactly one byte and returns null in the case that *either* nothing was read *or* a byte was read but it didn't make a message yet (notwithstanding the API documentation on `read()` claiming that it reads until no data is left in the buffer), I have to call `read()` in a loop until the buffer is empty, but I have no good way of knowing that. I tried calling `read()` exactly the number of times as the number of entries in the vector given to me by the `onReceived` signal, but it turns out this doesn't work either, because `UdpLink` fires the signal *before* it puts the data in its buffer, meaning I can get notified 30 bytes were received, and call `read()` 30 times, getting nothing each time, *before* `UdpLink` makes its newly received data available to be read.
To summarize:
* `PingDevice::waitMessage()` with UDP busy-loops for the duration of its timeout
* `UdpLink::read()` does not block the way the comment in `PingDevice::waitMessage()` claims it does
* `PingDevice::read()` does not exhaust the port buffer the way its API comment claims it does
* Ideally, `UdpLink` would emit the `onReceived` signal only after the data it's signalling about is actually available
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
Bắt đầu với test-device-ping360.cpp và các điểm vào PingDevice::waitMessage(), PingDevice::read(), UdpLink::read() và AbstractLink::doOnReceived() được mô tả trong issue. Truy vết quá trình dữ liệu UDP đến, bộ đệm và thứ tự của các signal, sau đó xác minh rằng thao tác chờ không chạy busy-loop, các lần đọc tuân theo hành vi được tài liệu hóa và onReceived được kích hoạt sau khi dữ liệu khả dụng.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- cpp
- Lĩnh vực
- networking
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 42/100