Move the fast-path checks from cleanup_(), process_to_add(), and
process_defer_queue_() into inline methods in the header. The common
case — nothing to clean up, nothing to add, nothing deferred — now
resolves with just an atomic load at the call site, avoiding a function
call into the .cpp translation unit entirely.
The slow paths remain in scheduler.cpp as cleanup_slow_path_(),
process_to_add_slow_path_(), and process_defer_queue_slow_path_().
Also moves the process_defer_queue_() body out of the header into
the .cpp file, reducing code bloat in every translation unit that
includes scheduler.h.
The test was calling show_logs() which invokes _wait_for_serial_port("/dev/ttyUSB0").
Since that path doesn't exist in CI/dev environments, it spun in a 30-second polling
loop before returning. Add mock_wait_for_serial_port fixture to skip the wait.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Add a comment to EventPool documenting that when paired with a
LockFreeQueue<T, N>, the pool should be sized to N-1 (the queue's
actual capacity) to prevent slot leaks and SPSC violations.
LockFreeQueue<T,N> is a ring buffer that holds N-1 elements (one slot
is reserved to distinguish full from empty). With the pool also sized
to N, the Nth allocate() succeeds but push() fails — permanently
leaking one pool slot since the element is never returned.
Size both receive and send pools to N-1 to match queue capacity.
LockFreeQueue<T,N> is a ring buffer that holds N-1 elements (one slot
is reserved to distinguish full from empty). With the pool also sized
to N, the Nth allocate() succeeds but push() fails — permanently
leaking one pool slot since the element is never returned.
Size the pool to N-1 to match queue capacity. This guarantees
allocate() returns nullptr before push() can fail.
The ESP-IDF MQTT client dispatches events from its own task, which
pushed to a std::queue while the main loop popped from it. std::queue
is not thread-safe; concurrent access can corrupt its internal state.
Replace with EventPool + LockFreeQueue (SPSC ring buffer) already
used elsewhere in the codebase. The pool is sized to queue capacity
(SIZE-1) so allocate() fails before push() can, which prevents both
a slot leak and an SPSC violation on the pool's free list.
Also rename the outbound pool from mqtt_event_pool_ to
mqtt_outbound_pool_ to avoid confusion with the new inbound pool.
On ESPHOME_THREAD_SINGLE there are no concurrent writers, so
to_add_empty_() checks to_add_.empty() directly. The counter
field and its increment/clear operations are compiled out.