Fix scheduler with too many cancelled timers (#1309)

* Fix scheduler with too many cancelled timers

* lint

* use variable name
This commit is contained in:
Guillermo Ruffino 2020-10-15 10:12:31 -03:00
parent 2c71ee7853
commit b38b7019ea
2 changed files with 26 additions and 1 deletions

View file

@ -8,6 +8,7 @@ namespace esphome {
static const char *TAG = "scheduler"; static const char *TAG = "scheduler";
static const uint32_t SCHEDULER_DONT_RUN = 4294967295UL; static const uint32_t SCHEDULER_DONT_RUN = 4294967295UL;
static const uint32_t MAX_LOGICALLY_DELETED_ITEMS = 10;
// Uncomment to debug scheduler // Uncomment to debug scheduler
// #define ESPHOME_DEBUG_SCHEDULER // #define ESPHOME_DEBUG_SCHEDULER
@ -107,6 +108,26 @@ void ICACHE_RAM_ATTR HOT Scheduler::call() {
} }
#endif // ESPHOME_DEBUG_SCHEDULER #endif // ESPHOME_DEBUG_SCHEDULER
auto to_remove_was = to_remove_;
auto items_was = items_.size();
// If we have too many items to remove
if (to_remove_ > MAX_LOGICALLY_DELETED_ITEMS) {
std::vector<std::unique_ptr<SchedulerItem>> valid_items;
while (!this->empty_()) {
auto item = std::move(this->items_[0]);
this->pop_raw_();
valid_items.push_back(std::move(item));
}
this->items_ = std::move(valid_items);
// The following should not happen unless I'm missing something
if (to_remove_ != 0) {
ESP_LOGW(TAG, "to_remove_ was %u now: %u items where %zu now %zu. Please report this", to_remove_was, to_remove_,
items_was, items_.size());
to_remove_ = 0;
}
}
while (!this->empty_()) { while (!this->empty_()) {
// use scoping to indicate visibility of `item` variable // use scoping to indicate visibility of `item` variable
{ {
@ -147,6 +168,7 @@ void ICACHE_RAM_ATTR HOT Scheduler::call() {
if (item->remove) { if (item->remove) {
// We were removed/cancelled in the function call, stop // We were removed/cancelled in the function call, stop
to_remove_--;
continue; continue;
} }
@ -182,6 +204,7 @@ void HOT Scheduler::cleanup_() {
if (!item->remove) if (!item->remove)
return; return;
to_remove_--;
this->pop_raw_(); this->pop_raw_();
} }
} }
@ -193,7 +216,8 @@ void HOT Scheduler::push_(std::unique_ptr<Scheduler::SchedulerItem> item) { this
bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, Scheduler::SchedulerItem::Type type) { bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, Scheduler::SchedulerItem::Type type) {
bool ret = false; bool ret = false;
for (auto &it : this->items_) for (auto &it : this->items_)
if (it->component == component && it->name == name && it->type == type) { if (it->component == component && it->name == name && it->type == type && !it->remove) {
to_remove_++;
it->remove = true; it->remove = true;
ret = true; ret = true;
} }

View file

@ -61,6 +61,7 @@ class Scheduler {
std::vector<std::unique_ptr<SchedulerItem>> to_add_; std::vector<std::unique_ptr<SchedulerItem>> to_add_;
uint32_t last_millis_{0}; uint32_t last_millis_{0};
uint8_t millis_major_{0}; uint8_t millis_major_{0};
uint32_t to_remove_{0};
}; };
} // namespace esphome } // namespace esphome