cleanup locking

This commit is contained in:
J. Nick Koston 2025-07-06 20:13:21 -05:00
parent dc8714c277
commit 2cfeccfd71
No known key found for this signature in database

View File

@ -294,29 +294,27 @@ void HOT Scheduler::call() {
} }
#endif // ESPHOME_DEBUG_SCHEDULER #endif // ESPHOME_DEBUG_SCHEDULER
auto to_remove_was = this->to_remove_;
auto items_was = this->items_.size();
// If we have too many items to remove // If we have too many items to remove
if (this->to_remove_ > MAX_LOGICALLY_DELETED_ITEMS) { if (this->to_remove_ > MAX_LOGICALLY_DELETED_ITEMS) {
// We hold the lock for the entire cleanup operation because:
// 1. We're rebuilding the entire items_ list, so we need exclusive access throughout
// 2. Other threads must see either the old state or the new state, not intermediate states
// 3. The operation is already expensive (O(n)), so lock overhead is negligible
// 4. No operations inside can block or take other locks, so no deadlock risk
LockGuard guard{this->lock_};
std::vector<std::unique_ptr<SchedulerItem>> valid_items; std::vector<std::unique_ptr<SchedulerItem>> valid_items;
while (!this->empty_()) {
LockGuard guard{this->lock_}; // Move all non-removed items to valid_items
auto item = std::move(this->items_[0]); for (auto &item : this->items_) {
this->pop_raw_(); if (!item->remove) {
valid_items.push_back(std::move(item)); valid_items.push_back(std::move(item));
}
} }
{ // Replace items_ with the filtered list
LockGuard guard{this->lock_}; this->items_ = std::move(valid_items);
this->items_ = std::move(valid_items); this->to_remove_ = 0;
}
// The following should not happen unless I'm missing something
if (this->to_remove_ != 0) {
ESP_LOGW(TAG, "to_remove_ was %" PRIu32 " now: %" PRIu32 " items where %zu now %zu. Please report this",
to_remove_was, to_remove_, items_was, items_.size());
this->to_remove_ = 0;
}
} }
while (!this->empty_()) { while (!this->empty_()) {