From e2c5eeef975fea9f814a191c2cc10fbe35698f68 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 5 Oct 2025 16:32:51 -0500 Subject: [PATCH] [scheduler] Deduplicate item removal code with template helper (#11017) --- esphome/core/scheduler.cpp | 26 +++++--------------------- esphome/core/scheduler.h | 27 +++++++++++++++++++-------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 71e2a00fbe..402084f306 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -118,7 +118,6 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type item->type = type; item->callback = std::move(func); // Initialize remove to false (though it should already be from constructor) - // Not using mark_item_removed_ helper since we're setting to false, not true #ifdef ESPHOME_THREAD_MULTI_ATOMICS item->remove.store(false, std::memory_order_relaxed); #else @@ -600,12 +599,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c #ifndef ESPHOME_THREAD_SINGLE // Mark items in defer queue as cancelled (they'll be skipped when processed) if (type == SchedulerItem::TIMEOUT) { - for (auto &item : this->defer_queue_) { - if (this->matches_item_(item, component, name_cstr, type, match_retry)) { - this->mark_item_removed_(item.get()); - total_cancelled++; - } - } + total_cancelled += this->mark_matching_items_removed_(this->defer_queue_, component, name_cstr, type, match_retry); } #endif /* not ESPHOME_THREAD_SINGLE */ @@ -620,23 +614,13 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c total_cancelled++; } // For other items in heap, we can only mark for removal (can't remove from middle of heap) - for (auto &item : this->items_) { - if (this->matches_item_(item, component, name_cstr, type, match_retry)) { - this->mark_item_removed_(item.get()); - total_cancelled++; - this->to_remove_++; // Track removals for heap items - } - } + size_t heap_cancelled = this->mark_matching_items_removed_(this->items_, component, name_cstr, type, match_retry); + total_cancelled += heap_cancelled; + this->to_remove_ += heap_cancelled; // Track removals for heap items } // Cancel items in to_add_ - for (auto &item : this->to_add_) { - if (this->matches_item_(item, component, name_cstr, type, match_retry)) { - this->mark_item_removed_(item.get()); - total_cancelled++; - // Don't track removals for to_add_ items - } - } + total_cancelled += this->mark_matching_items_removed_(this->to_add_, component, name_cstr, type, match_retry); return total_cancelled > 0; } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 885ee13754..2237915e07 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -280,19 +280,30 @@ class Scheduler { #endif } - // Helper to mark item for removal (platform-specific) + // Helper to mark matching items in a container as removed + // Returns the number of items marked for removal // For ESPHOME_THREAD_MULTI_NO_ATOMICS platforms, the caller must hold the scheduler lock before calling this // function. - void mark_item_removed_(SchedulerItem *item) { + template + size_t mark_matching_items_removed_(Container &container, Component *component, const char *name_cstr, + SchedulerItem::Type type, bool match_retry) { + size_t count = 0; + for (auto &item : container) { + if (this->matches_item_(item, component, name_cstr, type, match_retry)) { + // Mark item for removal (platform-specific) #ifdef ESPHOME_THREAD_MULTI_ATOMICS - // Multi-threaded with atomics: use atomic store - item->remove.store(true, std::memory_order_release); + // Multi-threaded with atomics: use atomic store + item->remove.store(true, std::memory_order_release); #else - // Single-threaded (ESPHOME_THREAD_SINGLE) or - // multi-threaded without atomics (ESPHOME_THREAD_MULTI_NO_ATOMICS): direct write - // For ESPHOME_THREAD_MULTI_NO_ATOMICS, caller MUST hold lock! - item->remove = true; + // Single-threaded (ESPHOME_THREAD_SINGLE) or + // multi-threaded without atomics (ESPHOME_THREAD_MULTI_NO_ATOMICS): direct write + // For ESPHOME_THREAD_MULTI_NO_ATOMICS, caller MUST hold lock! + item->remove = true; #endif + count++; + } + } + return count; } // Template helper to check if any item in a container matches our criteria