Handling queue overflow in LinkCable

This commit is contained in:
Rodrigo Alfonso 2025-01-14 11:26:46 -03:00
parent 64c02b816d
commit 30bd8a33cc
4 changed files with 30 additions and 1 deletions

View File

@ -126,6 +126,7 @@ You can also change these compile-time constants:
| `read(playerId)` | **u16** | Dequeues and returns the next message from player #`playerId`. If there's no data from that player, a `0` will be returned. |
| `peek(playerId)` | **u16** | Returns the next message from player #`playerId` without dequeuing it. If there's no data from that player, a `0` will be returned. |
| `send(data)` | - | Sends `data` to all connected players. If `data` is invalid or the send queue is full, a `false` will be returned. |
| `didReceiveQueueOverflow()` | **bool** | Returns whether the internal receive queue lost messages at some point due to being full. This can happen if your queue size is too low, if you receive too much data without calling `sync(...)` enough times, or if you don't `read(...)` enough messages before the next `sync()` call. The flag is cleared on each call. |
| `resetTimer()` | - | Restarts the send timer without disconnecting. Call this if you changed `config.interval` |
⚠️ `0xFFFF` and `0x0` are reserved values, so don't send them!

View File

@ -258,6 +258,26 @@ class LinkCable {
_state.outgoingMessages.syncPush(data);
}
/**
* @brief Returns whether the internal receive queue lost messages at some
* point due to being full. This can happen if your queue size is too low, if
* you receive too much data without calling `sync(...)` enough times, or if
* you don't `read(...)` enough messages before the next `sync()` call.
* \warning The flag is cleared on each call.
*/
[[nodiscard]] bool didReceiveQueueOverflow() {
bool overflow = false;
for (u32 i = 0; i < LINK_CABLE_MAX_PLAYERS; i++) {
overflow = overflow || _state.newMessages[i].overflow ||
_state.readyToSyncMessages[i].overflow;
_state.newMessages[i].overflow = false;
state.syncedIncomingMessages[i].overflow = false;
}
return overflow;
}
/**
* @brief Restarts the send timer without disconnecting.
* \warning Call this if you changed `config.interval`.
@ -431,6 +451,9 @@ class LinkCable {
_state.newMessages[i].clear();
setOffline(i);
_state.newMessages[i].overflow = false;
state.syncedIncomingMessages[i].overflow = false;
}
_state.IRQFlag = false;
_state.IRQTimeout = 0;
@ -476,7 +499,7 @@ class LinkCable {
}
void move(U16Queue& src, U16Queue& dst) {
while (!src.isEmpty())
while (!src.isEmpty() && !dst.isFull())
dst.push(src.pop());
}

View File

@ -73,6 +73,10 @@ bool C_LinkCable_send(C_LinkCableHandle handle, u16 data) {
return static_cast<LinkCable*>(handle)->send(data);
}
bool C_LinkCable_didReceiveQueueOverflow(C_LinkCableHandle handle) {
static_cast<LinkCable*>(handle)->didReceiveQueueOverflow();
}
void C_LinkCable_resetTimer(C_LinkCableHandle handle) {
static_cast<LinkCable*>(handle)->resetTimer();
}

View File

@ -57,6 +57,7 @@ u16 C_LinkCable_peek(C_LinkCableHandle handle, u8 playerId);
bool C_LinkCable_send(C_LinkCableHandle handle, u16 data);
bool C_LinkCable_didReceiveQueueOverflow(C_LinkCableHandle handle);
void C_LinkCable_resetTimer(C_LinkCableHandle handle);
C_LinkCable_Config C_LinkCable_getConfig(C_LinkCableHandle handle);