[esp32_ble] Fix EventPool/LockFreeQueue sizing off-by-one (#14892)

This commit is contained in:
J. Nick Koston
2026-03-17 12:24:02 -10:00
committed by GitHub
parent a94bb74d04
commit 1adf05e2d5
2 changed files with 9 additions and 2 deletions
+2 -1
View File
@@ -575,8 +575,9 @@ template<typename... Args> void enqueue_ble_event(Args... args) {
load_ble_event(event, args...);
// Push the event to the queue
// Push always succeeds: pool is sized to queue capacity (N-1), so if
// allocate() returned non-null, the queue is guaranteed to have room.
global_ble->ble_events_.push(event);
// Push always succeeds because we're the only producer and the pool ensures we never exceed queue size
}
// Explicit template instantiations for the friend function
+7 -1
View File
@@ -221,7 +221,13 @@ class ESP32BLE : public Component {
// Large objects (size depends on template parameters, but typically aligned to 4 bytes)
esphome::LockFreeQueue<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_events_;
esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_event_pool_;
// Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring
// buffer that holds N-1 elements (one slot distinguishes full from empty).
// This guarantees allocate() returns nullptr before push() can fail, which:
// 1. Prevents leaking a pool slot (the Nth allocate succeeds but push fails)
// 2. Avoids needing release() on the producer path after a failed push(),
// preserving the SPSC contract on the pool's internal free list
esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE - 1> ble_event_pool_;
// 4-byte aligned members
#ifdef USE_ESP32_BLE_ADVERTISING