mirror of
https://github.com/esphome/esphome.git
synced 2026-10-17 11:42:51 +00:00
[core][scheduler] add missing process_to_add call (#20961)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
co-authored by
J. Nick Koston
parent
107bebebad
commit
9031df757b
@@ -442,10 +442,10 @@ uint32_t HOT Scheduler::call(uint32_t now) {
|
||||
|
||||
SchedulerNameLog name_log;
|
||||
bool is_cancelled = is_item_removed_(item);
|
||||
ESP_LOGD(TAG, " %s '%s/%s' interval=%" PRIu32 " next_execution in %" PRIu64 "ms at %" PRIu64 "%s",
|
||||
ESP_LOGD(TAG, " %s '%s/%s' interval=%" PRIu32 " next_execution in %" PRId64 "ms at %" PRIu64 "%s",
|
||||
LOG_STR_ARG(item->get_type_str()), LOG_STR_ARG(item->get_source()),
|
||||
name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval,
|
||||
item->get_next_execution() - now_64, item->get_next_execution(),
|
||||
(int64_t) (item->get_next_execution() - now_64), item->get_next_execution(),
|
||||
is_cancelled ? LOG_STR_LITERAL(" [CANCELLED]") : LOG_STR_LITERAL(""));
|
||||
|
||||
old_items.push_back(item);
|
||||
@@ -539,6 +539,7 @@ uint32_t HOT Scheduler::call(uint32_t now) {
|
||||
// We were removed/cancelled in the function call, recycle and continue
|
||||
this->to_remove_decrement_locked_();
|
||||
this->recycle_item_main_loop_(executed_item);
|
||||
has_added_items |= !this->to_add_.empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/scheduler.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace esphome::core::testing {
|
||||
|
||||
class SchedulerTestComponent : public Component {};
|
||||
|
||||
// On a multi-threaded build next_schedule_in() only sees items_, so a timeout a callback leaves in
|
||||
// to_add_ would let a loop that sleeps on next_schedule_in() oversleep. The case that used to skip
|
||||
// the merge is a heap item (a zero timeout would run from the defer queue instead) whose callback
|
||||
// cancels its own item.
|
||||
TEST(Scheduler, TimeoutAddedByACancelledCallbackIsVisibleAfterCall) {
|
||||
Scheduler scheduler;
|
||||
SchedulerTestComponent component;
|
||||
bool fired = false;
|
||||
|
||||
scheduler.set_timeout(&component, "first", 1, [&]() {
|
||||
scheduler.cancel_timeout(&component, "first");
|
||||
scheduler.set_timeout(&component, "second", 100, [&fired]() { fired = true; });
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
scheduler.call(millis());
|
||||
|
||||
auto next = scheduler.next_schedule_in(millis());
|
||||
ASSERT_TRUE(next.has_value());
|
||||
const uint32_t next_ms = next.has_value() ? *next : 0;
|
||||
EXPECT_GT(next_ms, 50u);
|
||||
EXPECT_LE(next_ms, 100u);
|
||||
EXPECT_FALSE(fired);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(120));
|
||||
scheduler.call(millis());
|
||||
EXPECT_TRUE(fired);
|
||||
EXPECT_FALSE(scheduler.next_schedule_in(millis()).has_value());
|
||||
scheduler.trim_freelist();
|
||||
}
|
||||
|
||||
} // namespace esphome::core::testing
|
||||
Reference in New Issue
Block a user