1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-08 02:51:49 +00:00

[scheduler] Extract helper functions to improve code readability (#11730)

This commit is contained in:
J. Nick Koston
2025-11-05 12:13:12 -06:00
committed by GitHub
parent b7838671ae
commit df53ff7afe
2 changed files with 49 additions and 30 deletions

View File

@@ -117,12 +117,8 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type
item->set_name(name_cstr, !is_static_string); item->set_name(name_cstr, !is_static_string);
item->type = type; item->type = type;
item->callback = std::move(func); item->callback = std::move(func);
// Initialize remove to false (though it should already be from constructor) // Reset remove flag - recycled items may have been cancelled (remove=true) in previous use
#ifdef ESPHOME_THREAD_MULTI_ATOMICS this->set_item_removed_(item.get(), false);
item->remove.store(false, std::memory_order_relaxed);
#else
item->remove = false;
#endif
item->is_retry = is_retry; item->is_retry = is_retry;
#ifndef ESPHOME_THREAD_SINGLE #ifndef ESPHOME_THREAD_SINGLE
@@ -153,21 +149,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type
} }
#ifdef ESPHOME_DEBUG_SCHEDULER #ifdef ESPHOME_DEBUG_SCHEDULER
// Validate static strings in debug mode this->debug_log_timer_(item.get(), is_static_string, name_cstr, type, delay, now);
if (is_static_string && name_cstr != nullptr) {
validate_static_string(name_cstr);
}
// Debug logging
const char *type_str = (type == SchedulerItem::TIMEOUT) ? "timeout" : "interval";
if (type == SchedulerItem::TIMEOUT) {
ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()),
name_cstr ? name_cstr : "(null)", type_str, delay);
} else {
ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ", offset=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()),
name_cstr ? name_cstr : "(null)", type_str, delay,
static_cast<uint32_t>(item->get_next_execution() - now));
}
#endif /* ESPHOME_DEBUG_SCHEDULER */ #endif /* ESPHOME_DEBUG_SCHEDULER */
// For retries, check if there's a cancelled timeout first // For retries, check if there's a cancelled timeout first
@@ -787,4 +769,25 @@ void Scheduler::recycle_item_(std::unique_ptr<SchedulerItem> item) {
// else: unique_ptr will delete the item when it goes out of scope // else: unique_ptr will delete the item when it goes out of scope
} }
#ifdef ESPHOME_DEBUG_SCHEDULER
void Scheduler::debug_log_timer_(const SchedulerItem *item, bool is_static_string, const char *name_cstr,
SchedulerItem::Type type, uint32_t delay, uint64_t now) {
// Validate static strings in debug mode
if (is_static_string && name_cstr != nullptr) {
validate_static_string(name_cstr);
}
// Debug logging
const char *type_str = (type == SchedulerItem::TIMEOUT) ? "timeout" : "interval";
if (type == SchedulerItem::TIMEOUT) {
ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()),
name_cstr ? name_cstr : "(null)", type_str, delay);
} else {
ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ", offset=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()),
name_cstr ? name_cstr : "(null)", type_str, delay,
static_cast<uint32_t>(item->get_next_execution() - now));
}
}
#endif /* ESPHOME_DEBUG_SCHEDULER */
} // namespace esphome } // namespace esphome

View File

@@ -266,6 +266,12 @@ class Scheduler {
// Helper to perform full cleanup when too many items are cancelled // Helper to perform full cleanup when too many items are cancelled
void full_cleanup_removed_items_(); void full_cleanup_removed_items_();
#ifdef ESPHOME_DEBUG_SCHEDULER
// Helper for debug logging in set_timer_common_ - extracted to reduce code size
void debug_log_timer_(const SchedulerItem *item, bool is_static_string, const char *name_cstr,
SchedulerItem::Type type, uint32_t delay, uint64_t now);
#endif /* ESPHOME_DEBUG_SCHEDULER */
#ifndef ESPHOME_THREAD_SINGLE #ifndef ESPHOME_THREAD_SINGLE
// Helper to process defer queue - inline for performance in hot path // Helper to process defer queue - inline for performance in hot path
inline void process_defer_queue_(uint32_t &now) { inline void process_defer_queue_(uint32_t &now) {
@@ -367,6 +373,24 @@ class Scheduler {
#endif #endif
} }
// Helper to set item removal flag (platform-specific)
// For ESPHOME_THREAD_MULTI_NO_ATOMICS platforms, the caller must hold the scheduler lock before calling this
// function. Uses memory_order_release when setting to true (for cancellation synchronization),
// and memory_order_relaxed when setting to false (for initialization).
void set_item_removed_(SchedulerItem *item, bool removed) {
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
// Multi-threaded with atomics: use atomic store with appropriate ordering
// Release ordering when setting to true ensures cancellation is visible to other threads
// Relaxed ordering when setting to false is sufficient for initialization
item->remove.store(removed, removed ? std::memory_order_release : std::memory_order_relaxed);
#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 = removed;
#endif
}
// Helper to mark matching items in a container as removed // Helper to mark matching items in a container as removed
// Returns the number of items marked for removal // Returns the number of items marked for removal
// IMPORTANT: Caller must hold the scheduler lock before calling this function. // IMPORTANT: Caller must hold the scheduler lock before calling this function.
@@ -383,15 +407,7 @@ class Scheduler {
continue; continue;
if (this->matches_item_(item, component, name_cstr, type, match_retry)) { if (this->matches_item_(item, component, name_cstr, type, match_retry)) {
// Mark item for removal (platform-specific) // Mark item for removal (platform-specific)
#ifdef ESPHOME_THREAD_MULTI_ATOMICS this->set_item_removed_(item.get(), true);
// 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;
#endif
count++; count++;
} }
} }