mirror of
https://github.com/esphome/esphome.git
synced 2025-09-10 15:22:24 +01:00
Merge branch 'integration' into memory_api
This commit is contained in:
@@ -436,85 +436,79 @@ void HOT Scheduler::call(uint32_t now) {
|
|||||||
this->to_remove_ = 0;
|
this->to_remove_ = 0;
|
||||||
}
|
}
|
||||||
while (!this->items_.empty()) {
|
while (!this->items_.empty()) {
|
||||||
// use scoping to indicate visibility of `item` variable
|
// Don't copy-by value yet
|
||||||
{
|
auto &item = this->items_[0];
|
||||||
// Don't copy-by value yet
|
if (item->get_next_execution() > now_64) {
|
||||||
auto &item = this->items_[0];
|
// Not reached timeout yet, done for this call
|
||||||
if (item->get_next_execution() > now_64) {
|
break;
|
||||||
// Not reached timeout yet, done for this call
|
}
|
||||||
break;
|
// Don't run on failed components
|
||||||
}
|
if (item->component != nullptr && item->component->is_failed()) {
|
||||||
// Don't run on failed components
|
LockGuard guard{this->lock_};
|
||||||
if (item->component != nullptr && item->component->is_failed()) {
|
this->pop_raw_();
|
||||||
LockGuard guard{this->lock_};
|
continue;
|
||||||
this->pop_raw_();
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if item is marked for removal
|
// Check if item is marked for removal
|
||||||
// This handles two cases:
|
// This handles two cases:
|
||||||
// 1. Item was marked for removal after cleanup_() but before we got here
|
// 1. Item was marked for removal after cleanup_() but before we got here
|
||||||
// 2. Item is marked for removal but wasn't at the front of the heap during cleanup_()
|
// 2. Item is marked for removal but wasn't at the front of the heap during cleanup_()
|
||||||
#ifdef ESPHOME_THREAD_MULTI_NO_ATOMICS
|
#ifdef ESPHOME_THREAD_MULTI_NO_ATOMICS
|
||||||
// Multi-threaded platforms without atomics: must take lock to safely read remove flag
|
// Multi-threaded platforms without atomics: must take lock to safely read remove flag
|
||||||
{
|
{
|
||||||
LockGuard guard{this->lock_};
|
LockGuard guard{this->lock_};
|
||||||
if (is_item_removed_(item.get())) {
|
|
||||||
this->pop_raw_();
|
|
||||||
this->to_remove_--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Single-threaded or multi-threaded with atomics: can check without lock
|
|
||||||
if (is_item_removed_(item.get())) {
|
if (is_item_removed_(item.get())) {
|
||||||
LockGuard guard{this->lock_};
|
|
||||||
this->pop_raw_();
|
this->pop_raw_();
|
||||||
this->to_remove_--;
|
this->to_remove_--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Single-threaded or multi-threaded with atomics: can check without lock
|
||||||
|
if (is_item_removed_(item.get())) {
|
||||||
|
LockGuard guard{this->lock_};
|
||||||
|
this->pop_raw_();
|
||||||
|
this->to_remove_--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESPHOME_DEBUG_SCHEDULER
|
#ifdef ESPHOME_DEBUG_SCHEDULER
|
||||||
const char *item_name = item->get_name();
|
const char *item_name = item->get_name();
|
||||||
ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")",
|
ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")",
|
||||||
item->get_type_str(), LOG_STR_ARG(item->get_source()), item_name ? item_name : "(null)", item->interval,
|
item->get_type_str(), LOG_STR_ARG(item->get_source()), item_name ? item_name : "(null)", item->interval,
|
||||||
item->get_next_execution(), now_64);
|
item->get_next_execution(), now_64);
|
||||||
#endif /* ESPHOME_DEBUG_SCHEDULER */
|
#endif /* ESPHOME_DEBUG_SCHEDULER */
|
||||||
|
|
||||||
// Warning: During callback(), a lot of stuff can happen, including:
|
// Warning: During callback(), a lot of stuff can happen, including:
|
||||||
// - timeouts/intervals get added, potentially invalidating vector pointers
|
// - timeouts/intervals get added, potentially invalidating vector pointers
|
||||||
// - timeouts/intervals get cancelled
|
// - timeouts/intervals get cancelled
|
||||||
this->execute_item_(item.get(), now);
|
this->execute_item_(item.get(), now);
|
||||||
|
|
||||||
|
LockGuard guard{this->lock_};
|
||||||
|
|
||||||
|
auto executed_item = std::move(this->items_[0]);
|
||||||
|
// Only pop after function call, this ensures we were reachable
|
||||||
|
// during the function call and know if we were cancelled.
|
||||||
|
this->pop_raw_();
|
||||||
|
|
||||||
|
if (executed_item->remove) {
|
||||||
|
// We were removed/cancelled in the function call, stop
|
||||||
|
this->to_remove_--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (executed_item->type == SchedulerItem::INTERVAL) {
|
||||||
LockGuard guard{this->lock_};
|
executed_item->set_next_execution(now_64 + executed_item->interval);
|
||||||
|
// Add new item directly to to_add_
|
||||||
// new scope, item from before might have been moved in the vector
|
// since we have the lock held
|
||||||
auto item = std::move(this->items_[0]);
|
this->to_add_.push_back(std::move(executed_item));
|
||||||
// Only pop after function call, this ensures we were reachable
|
} else {
|
||||||
// during the function call and know if we were cancelled.
|
// Timeout completed - recycle it
|
||||||
this->pop_raw_();
|
this->recycle_item_(std::move(executed_item));
|
||||||
|
|
||||||
if (item->remove) {
|
|
||||||
// We were removed/cancelled in the function call, stop
|
|
||||||
this->to_remove_--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item->type == SchedulerItem::INTERVAL) {
|
|
||||||
item->set_next_execution(now_64 + item->interval);
|
|
||||||
// Add new item directly to to_add_
|
|
||||||
// since we have the lock held
|
|
||||||
this->to_add_.push_back(std::move(item));
|
|
||||||
} else {
|
|
||||||
// Timeout completed - recycle it
|
|
||||||
this->recycle_item_(std::move(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
has_added_items |= !this->to_add_.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_added_items |= !this->to_add_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_added_items) {
|
if (has_added_items) {
|
||||||
|
Reference in New Issue
Block a user