mirror of
https://github.com/esphome/esphome.git
synced 2026-09-02 02:56:01 +00:00
[core] Scheduler::next_schedule_in: also handle single-threaded defer path
On ESPHOME_THREAD_SINGLE builds (ESP8266, RP2040), defer() does not route through defer_queue_ — set_timer_common_ treats it as an ordinary 0-delay set_timeout that stages in to_add_ (scheduler.cpp:197). Since next_schedule_in only inspects items_[0], any defer posted from a component's loop() sits in to_add_ invisible to the sleep calculation until the next scheduler.call() runs process_to_add(). The symmetric fix checks to_add_empty_() on single-threaded and short-circuits sleep the same way. This also costs one "skipped sleep" for any non-zero-delay timer added at runtime, but the next tick produces a correct next_schedule_in reading and the cost is a single yield — negligible vs. the stall this closes. Suggested by Copilot review on #15968.
This commit is contained in:
@@ -423,6 +423,12 @@ optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) {
|
||||
// iteration has work to do right now -- don't let the caller sleep.
|
||||
if (!this->defer_empty_())
|
||||
return 0;
|
||||
#else
|
||||
// On single-threaded builds, defer() routes through set_timeout(..., 0) which
|
||||
// stages in to_add_. process_to_add() runs at the top of every scheduler.call(),
|
||||
// so anything in to_add_ becomes runnable on the next iteration; don't sleep.
|
||||
if (!this->to_add_empty_())
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
// If no items, return empty optional
|
||||
|
||||
Reference in New Issue
Block a user