16static const char *
const TAG =
"scheduler";
25static constexpr size_t MAX_POOL_SIZE = 5;
30static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5;
32static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2;
34static constexpr uint32_t MAX_INTERVAL_DELAY = 5000;
36#if defined(ESPHOME_LOG_HAS_VERBOSE) || defined(ESPHOME_DEBUG_SCHEDULER)
40struct SchedulerNameLog {
45 const char *format(Scheduler::NameType name_type,
const char *static_name, uint32_t hash_or_id) {
46 using NameType = Scheduler::NameType;
47 if (name_type == NameType::STATIC_STRING) {
51 ESPHOME_strncpy_P(buffer, ESPHOME_PSTR(
"(null)"),
sizeof(buffer));
53 }
else if (name_type == NameType::HASHED_STRING) {
54 ESPHOME_snprintf_P(buffer,
sizeof(buffer), ESPHOME_PSTR(
"hash:0x%08" PRIX32), hash_or_id);
57 ESPHOME_snprintf_P(buffer,
sizeof(buffer), ESPHOME_PSTR(
"id:%" PRIu32), hash_or_id);
67#ifdef ESPHOME_DEBUG_SCHEDULER
69static void validate_static_string(
const char *name) {
75 uintptr_t addr =
reinterpret_cast<uintptr_t
>(name);
79 uintptr_t stack_addr =
reinterpret_cast<uintptr_t
>(&stack_var);
83 if (addr > (stack_addr - 0x2000) && addr < (stack_addr + 0x2000)) {
85 "WARNING: Scheduler name '%s' at %p appears to be on the stack - this is unsafe!\n"
86 " Stack reference at %p",
87 name, name, &stack_var);
92 static const char *static_str =
"test";
93 uintptr_t static_addr =
reinterpret_cast<uintptr_t
>(static_str);
96 if (addr > static_addr + 0x100000 || (static_addr > 0x100000 && addr < static_addr - 0x100000)) {
97 ESP_LOGW(TAG,
"WARNING: Scheduler name '%s' at %p might be on heap (static ref at %p)", name, name, static_str);
109void HOT Scheduler::set_timer_common_(Component *
component, SchedulerItem::Type
type, NameType name_type,
110 const char *static_name, uint32_t hash_or_id, uint32_t
delay,
111 std::function<
void()> func,
bool is_retry,
bool skip_cancel) {
112 if (
delay == SCHEDULER_DONT_RUN) {
115 LockGuard guard{this->lock_};
116 this->cancel_item_locked_(
component, name_type, static_name, hash_or_id,
type);
122 const uint64_t now = this->millis_64_(
millis());
125 LockGuard guard{this->lock_};
128 auto item = this->get_item_from_pool_locked_();
131 case NameType::STATIC_STRING:
132 item->set_static_name(static_name);
134 case NameType::HASHED_STRING:
135 item->set_hashed_name(hash_or_id);
137 case NameType::NUMERIC_ID:
138 item->set_numeric_id(hash_or_id);
142 item->callback = std::move(func);
144 this->set_item_removed_(item.get(),
false);
145 item->is_retry = is_retry;
147#ifndef ESPHOME_THREAD_SINGLE
150 if (
delay == 0 &&
type == SchedulerItem::TIMEOUT) {
153 this->cancel_item_locked_(
component, name_type, static_name, hash_or_id,
type);
155 this->defer_queue_.push_back(std::move(item));
161 if (
type == SchedulerItem::INTERVAL) {
162 item->interval =
delay;
166 item->set_next_execution(now + offset);
167#ifdef ESPHOME_LOG_HAS_VERBOSE
168 SchedulerNameLog name_log;
169 ESP_LOGV(TAG,
"Scheduler interval for %s is %" PRIu32
"ms, offset %" PRIu32
"ms",
170 name_log.format(name_type, static_name, hash_or_id),
delay, offset);
174 item->set_next_execution(now +
delay);
177#ifdef ESPHOME_DEBUG_SCHEDULER
178 this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id,
type,
delay, now);
183 if (is_retry && (name_type != NameType::STATIC_STRING || static_name !=
nullptr) &&
type == SchedulerItem::TIMEOUT &&
184 (has_cancelled_timeout_in_container_locked_(this->items_,
component, name_type, static_name, hash_or_id,
186 has_cancelled_timeout_in_container_locked_(this->to_add_,
component, name_type, static_name, hash_or_id,
189#ifdef ESPHOME_DEBUG_SCHEDULER
190 SchedulerNameLog skip_name_log;
191 ESP_LOGD(TAG,
"Skipping retry '%s' - found cancelled item",
192 skip_name_log.format(name_type, static_name, hash_or_id));
200 this->cancel_item_locked_(
component, name_type, static_name, hash_or_id,
type);
204 this->to_add_.push_back(std::move(item));
207void HOT Scheduler::set_timeout(Component *
component,
const char *name, uint32_t timeout, std::function<
void()> func) {
208 this->set_timer_common_(
component, SchedulerItem::TIMEOUT, NameType::STATIC_STRING, name, 0, timeout,
212void HOT Scheduler::set_timeout(Component *
component,
const std::string &name, uint32_t timeout,
213 std::function<
void()> func) {
214 this->set_timer_common_(
component, SchedulerItem::TIMEOUT, NameType::HASHED_STRING,
nullptr,
fnv1a_hash(name),
215 timeout, std::move(func));
217void HOT Scheduler::set_timeout(Component *
component, uint32_t
id, uint32_t timeout, std::function<
void()> func) {
218 this->set_timer_common_(
component, SchedulerItem::TIMEOUT, NameType::NUMERIC_ID,
nullptr,
id, timeout,
221bool HOT Scheduler::cancel_timeout(Component *
component,
const std::string &name) {
222 return this->cancel_item_(
component, NameType::HASHED_STRING,
nullptr,
fnv1a_hash(name), SchedulerItem::TIMEOUT);
224bool HOT Scheduler::cancel_timeout(Component *
component,
const char *name) {
225 return this->cancel_item_(
component, NameType::STATIC_STRING, name, 0, SchedulerItem::TIMEOUT);
227bool HOT Scheduler::cancel_timeout(Component *
component, uint32_t
id) {
228 return this->cancel_item_(
component, NameType::NUMERIC_ID,
nullptr,
id, SchedulerItem::TIMEOUT);
230void HOT Scheduler::set_interval(Component *
component,
const std::string &name, uint32_t interval,
231 std::function<
void()> func) {
232 this->set_timer_common_(
component, SchedulerItem::INTERVAL, NameType::HASHED_STRING,
nullptr,
fnv1a_hash(name),
233 interval, std::move(func));
236void HOT Scheduler::set_interval(Component *
component,
const char *name, uint32_t interval,
237 std::function<
void()> func) {
238 this->set_timer_common_(
component, SchedulerItem::INTERVAL, NameType::STATIC_STRING, name, 0, interval,
241void HOT Scheduler::set_interval(Component *
component, uint32_t
id, uint32_t interval, std::function<
void()> func) {
242 this->set_timer_common_(
component, SchedulerItem::INTERVAL, NameType::NUMERIC_ID,
nullptr,
id, interval,
245bool HOT Scheduler::cancel_interval(Component *
component,
const std::string &name) {
246 return this->cancel_item_(
component, NameType::HASHED_STRING,
nullptr,
fnv1a_hash(name), SchedulerItem::INTERVAL);
248bool HOT Scheduler::cancel_interval(Component *
component,
const char *name) {
249 return this->cancel_item_(
component, NameType::STATIC_STRING, name, 0, SchedulerItem::INTERVAL);
251bool HOT Scheduler::cancel_interval(Component *
component, uint32_t
id) {
252 return this->cancel_item_(
component, NameType::NUMERIC_ID,
nullptr,
id, SchedulerItem::INTERVAL);
259 Scheduler *scheduler;
262 const char *static_name;
266 float backoff_increase_factor;
267 Scheduler::NameType name_type;
268 uint8_t retry_countdown;
272 RetryResult const retry_result = args->func(--args->retry_countdown);
278 const char *static_name = (args->name_type == Scheduler::NameType::STATIC_STRING) ? args->name_.static_name :
nullptr;
279 uint32_t hash_or_id = (args->name_type != Scheduler::NameType::STATIC_STRING) ? args->name_.hash_or_id : 0;
280 args->scheduler->set_timer_common_(
281 args->component, Scheduler::SchedulerItem::TIMEOUT, args->name_type, static_name, hash_or_id,
282 args->current_interval, [args]() { retry_handler(args); },
285 args->current_interval *= args->backoff_increase_factor;
288void HOT Scheduler::set_retry_common_(Component *
component, NameType name_type,
const char *static_name,
289 uint32_t hash_or_id, uint32_t initial_wait_time, uint8_t max_attempts,
290 std::function<
RetryResult(uint8_t)> func,
float backoff_increase_factor) {
291 this->cancel_retry_(
component, name_type, static_name, hash_or_id);
293 if (initial_wait_time == SCHEDULER_DONT_RUN)
296#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
298 SchedulerNameLog name_log;
299 ESP_LOGVV(TAG,
"set_retry(name='%s', initial_wait_time=%" PRIu32
", max_attempts=%u, backoff_factor=%0.1f)",
300 name_log.format(name_type, static_name, hash_or_id), initial_wait_time, max_attempts,
301 backoff_increase_factor);
305 if (backoff_increase_factor < 0.0001) {
306 ESP_LOGE(TAG,
"set_retry: backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor,
307 (name_type == NameType::STATIC_STRING && static_name) ? static_name :
"");
308 backoff_increase_factor = 1;
311 auto args = std::make_shared<RetryArgs>();
312 args->func = std::move(func);
314 args->scheduler =
this;
315 args->name_type = name_type;
316 if (name_type == NameType::STATIC_STRING) {
317 args->name_.static_name = static_name;
319 args->name_.hash_or_id = hash_or_id;
321 args->current_interval = initial_wait_time;
322 args->backoff_increase_factor = backoff_increase_factor;
323 args->retry_countdown = max_attempts;
326 this->set_timer_common_(
327 component, SchedulerItem::TIMEOUT, name_type, static_name, hash_or_id, 0, [args]() {
retry_handler(args); },
331void HOT Scheduler::set_retry(Component *
component,
const char *name, uint32_t initial_wait_time, uint8_t max_attempts,
332 std::function<
RetryResult(uint8_t)> func,
float backoff_increase_factor) {
333 this->set_retry_common_(
component, NameType::STATIC_STRING, name, 0, initial_wait_time, max_attempts, std::move(func),
334 backoff_increase_factor);
337bool HOT Scheduler::cancel_retry_(Component *
component, NameType name_type,
const char *static_name,
338 uint32_t hash_or_id) {
339 return this->cancel_item_(
component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT,
342bool HOT Scheduler::cancel_retry(Component *
component,
const char *name) {
343 return this->cancel_retry_(
component, NameType::STATIC_STRING, name, 0);
346void HOT Scheduler::set_retry(Component *
component,
const std::string &name, uint32_t initial_wait_time,
347 uint8_t max_attempts, std::function<
RetryResult(uint8_t)> func,
348 float backoff_increase_factor) {
349 this->set_retry_common_(
component, NameType::HASHED_STRING,
nullptr,
fnv1a_hash(name), initial_wait_time,
350 max_attempts, std::move(func), backoff_increase_factor);
353bool HOT Scheduler::cancel_retry(Component *
component,
const std::string &name) {
357void HOT Scheduler::set_retry(Component *
component, uint32_t
id, uint32_t initial_wait_time, uint8_t max_attempts,
358 std::function<
RetryResult(uint8_t)> func,
float backoff_increase_factor) {
359 this->set_retry_common_(
component, NameType::NUMERIC_ID,
nullptr,
id, initial_wait_time, max_attempts,
360 std::move(func), backoff_increase_factor);
363bool HOT Scheduler::cancel_retry(Component *
component, uint32_t
id) {
364 return this->cancel_retry_(
component, NameType::NUMERIC_ID,
nullptr,
id);
367optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) {
373 if (this->cleanup_() == 0)
376 auto &item = this->items_[0];
378 const auto now_64 = this->millis_64_(now);
379 const uint64_t next_exec = item->get_next_execution();
380 if (next_exec < now_64)
382 return next_exec - now_64;
385void Scheduler::full_cleanup_removed_items_() {
391 LockGuard guard{this->lock_};
393 std::vector<std::unique_ptr<SchedulerItem>> valid_items;
396 for (
auto &item : this->items_) {
397 if (!is_item_removed_(item.get())) {
398 valid_items.push_back(std::move(item));
401 this->recycle_item_main_loop_(std::move(item));
406 this->items_ = std::move(valid_items);
408 std::make_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp);
409 this->to_remove_ = 0;
412void HOT Scheduler::call(uint32_t now) {
413#ifndef ESPHOME_THREAD_SINGLE
414 this->process_defer_queue_(now);
418 const auto now_64 = this->millis_64_(now);
419 this->process_to_add();
422 bool has_added_items =
false;
424#ifdef ESPHOME_DEBUG_SCHEDULER
425 static uint64_t last_print = 0;
427 if (now_64 - last_print > 2000) {
429 std::vector<std::unique_ptr<SchedulerItem>> old_items;
430#ifdef ESPHOME_THREAD_MULTI_ATOMICS
431 const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed);
432 const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed);
433 ESP_LOGD(TAG,
"Items: count=%zu, pool=%zu, now=%" PRIu64
" (%" PRIu16
", %" PRIu32
")", this->items_.size(),
434 this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg);
436 ESP_LOGD(TAG,
"Items: count=%zu, pool=%zu, now=%" PRIu64
" (%" PRIu16
", %" PRIu32
")", this->items_.size(),
437 this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_);
441 while (!this->items_.empty()) {
442 std::unique_ptr<SchedulerItem> item;
444 LockGuard guard{this->lock_};
445 item = this->pop_raw_locked_();
448 SchedulerNameLog name_log;
449 bool is_cancelled = is_item_removed_(item.get());
450 ESP_LOGD(TAG,
" %s '%s/%s' interval=%" PRIu32
" next_execution in %" PRIu64
"ms at %" PRIu64
"%s",
451 item->get_type_str(), LOG_STR_ARG(item->get_source()),
452 name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval,
453 item->get_next_execution() - now_64, item->get_next_execution(), is_cancelled ?
" [CANCELLED]" :
"");
455 old_items.push_back(std::move(item));
460 LockGuard guard{this->lock_};
461 this->items_ = std::move(old_items);
463 std::make_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp);
474 if (this->to_remove_ >= MAX_LOGICALLY_DELETED_ITEMS) {
475 this->full_cleanup_removed_items_();
477 while (!this->items_.empty()) {
479 auto &item = this->items_[0];
480 if (item->get_next_execution() > now_64) {
485 if (item->component !=
nullptr && item->component->is_failed()) {
486 LockGuard guard{this->lock_};
487 this->recycle_item_main_loop_(this->pop_raw_locked_());
495#ifdef ESPHOME_THREAD_MULTI_NO_ATOMICS
498 LockGuard guard{this->lock_};
499 if (is_item_removed_(item.get())) {
500 this->recycle_item_main_loop_(this->pop_raw_locked_());
507 if (is_item_removed_(item.get())) {
508 LockGuard guard{this->lock_};
509 this->recycle_item_main_loop_(this->pop_raw_locked_());
515#ifdef ESPHOME_DEBUG_SCHEDULER
517 SchedulerNameLog name_log;
518 ESP_LOGV(TAG,
"Running %s '%s/%s' with interval=%" PRIu32
" next_execution=%" PRIu64
" (now=%" PRIu64
")",
519 item->get_type_str(), LOG_STR_ARG(item->get_source()),
520 name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval,
521 item->get_next_execution(), now_64);
528 now = this->execute_item_(item.get(), now);
530 LockGuard guard{this->lock_};
534 auto executed_item = this->pop_raw_locked_();
536 if (executed_item->remove) {
539 this->recycle_item_main_loop_(std::move(executed_item));
543 if (executed_item->type == SchedulerItem::INTERVAL) {
544 executed_item->set_next_execution(now_64 + executed_item->interval);
547 this->to_add_.push_back(std::move(executed_item));
550 this->recycle_item_main_loop_(std::move(executed_item));
553 has_added_items |= !this->to_add_.empty();
556 if (has_added_items) {
557 this->process_to_add();
560void HOT Scheduler::process_to_add() {
561 LockGuard guard{this->lock_};
562 for (
auto &it : this->to_add_) {
563 if (is_item_removed_(it.get())) {
565 this->recycle_item_main_loop_(std::move(it));
569 this->items_.push_back(std::move(it));
570 std::push_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp);
572 this->to_add_.clear();
574size_t HOT Scheduler::cleanup_() {
582 if (this->to_remove_ == 0)
583 return this->items_.size();
593 LockGuard guard{this->lock_};
594 while (!this->items_.empty()) {
595 auto &item = this->items_[0];
599 this->recycle_item_main_loop_(this->pop_raw_locked_());
601 return this->items_.size();
603std::unique_ptr<Scheduler::SchedulerItem> HOT Scheduler::pop_raw_locked_() {
604 std::pop_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp);
607 auto item = std::move(this->items_.back());
609 this->items_.pop_back();
614uint32_t HOT Scheduler::execute_item_(SchedulerItem *item, uint32_t now) {
616 WarnIfComponentBlockingGuard guard{item->component, now};
618 return guard.finish();
622bool HOT Scheduler::cancel_item_(Component *
component, NameType name_type,
const char *static_name, uint32_t hash_or_id,
623 SchedulerItem::Type
type,
bool match_retry) {
624 LockGuard guard{this->lock_};
625 return this->cancel_item_locked_(
component, name_type, static_name, hash_or_id,
type, match_retry);
630bool HOT Scheduler::cancel_item_locked_(Component *
component, NameType name_type,
const char *static_name,
631 uint32_t hash_or_id, SchedulerItem::Type
type,
bool match_retry) {
633 if (name_type == NameType::STATIC_STRING && static_name ==
nullptr) {
637 size_t total_cancelled = 0;
639#ifndef ESPHOME_THREAD_SINGLE
641 if (
type == SchedulerItem::TIMEOUT) {
642 total_cancelled += this->mark_matching_items_removed_locked_(this->defer_queue_,
component, name_type, static_name,
643 hash_or_id,
type, match_retry);
652 if (!this->items_.empty()) {
653 size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_,
component, name_type, static_name,
654 hash_or_id,
type, match_retry);
655 total_cancelled += heap_cancelled;
656 this->to_remove_ += heap_cancelled;
660 total_cancelled += this->mark_matching_items_removed_locked_(this->to_add_,
component, name_type, static_name,
661 hash_or_id,
type, match_retry);
663 return total_cancelled > 0;
666uint64_t Scheduler::millis_64_(uint32_t now) {
681#ifdef ESPHOME_THREAD_SINGLE
687 uint16_t major = this->millis_major_;
691 if (now < last && (last - now) > HALF_MAX_UINT32) {
692 this->millis_major_++;
694 this->last_millis_ = now;
695#ifdef ESPHOME_DEBUG_SCHEDULER
696 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
698 }
else if (now > last) {
700 this->last_millis_ = now;
704 return now + (
static_cast<uint64_t
>(major) << 32);
706#elif defined(ESPHOME_THREAD_MULTI_NO_ATOMICS)
714 uint16_t major = this->millis_major_;
719 static const uint32_t ROLLOVER_WINDOW = 10000;
722 bool near_rollover = (last > (std::numeric_limits<uint32_t>::max() - ROLLOVER_WINDOW)) || (now < ROLLOVER_WINDOW);
724 if (near_rollover || (now < last && (last - now) > HALF_MAX_UINT32)) {
726 LockGuard guard{this->lock_};
728 last = this->last_millis_;
730 if (now < last && (last - now) > HALF_MAX_UINT32) {
732 this->millis_major_++;
734#ifdef ESPHOME_DEBUG_SCHEDULER
735 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
739 this->last_millis_ = now;
740 }
else if (now > last) {
747 this->last_millis_ = now;
753 return now + (
static_cast<uint64_t
>(major) << 32);
755#elif defined(ESPHOME_THREAD_MULTI_ATOMICS)
766 uint16_t major = this->millis_major_.load(std::memory_order_acquire);
774 uint32_t last = this->last_millis_.load(std::memory_order_acquire);
778 if (now < last && (last - now) > HALF_MAX_UINT32) {
780 LockGuard guard{this->lock_};
782 last = this->last_millis_.load(std::memory_order_relaxed);
784 if (now < last && (last - now) > HALF_MAX_UINT32) {
786 this->millis_major_.fetch_add(1, std::memory_order_relaxed);
788#ifdef ESPHOME_DEBUG_SCHEDULER
789 ESP_LOGD(TAG,
"Detected true 32-bit rollover at %" PRIu32
"ms (was %" PRIu32
")", now, last);
797 this->last_millis_.store(now, std::memory_order_release);
801 while (now > last && (now - last) < HALF_MAX_UINT32) {
802 if (this->last_millis_.compare_exchange_weak(last, now,
803 std::memory_order_release,
804 std::memory_order_relaxed)) {
811 uint16_t major_end = this->millis_major_.load(std::memory_order_relaxed);
812 if (major_end == major)
813 return now + (
static_cast<uint64_t
>(major) << 32);
816 __builtin_unreachable();
820 "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined."
824bool HOT Scheduler::SchedulerItem::cmp(
const std::unique_ptr<SchedulerItem> &a,
825 const std::unique_ptr<SchedulerItem> &b) {
828 return (a->next_execution_high_ == b->next_execution_high_) ? (a->next_execution_low_ > b->next_execution_low_)
829 : (a->next_execution_high_ > b->next_execution_high_);
836void Scheduler::recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item) {
840 if (this->scheduler_item_pool_.size() < MAX_POOL_SIZE) {
842 item->callback =
nullptr;
843 this->scheduler_item_pool_.push_back(std::move(item));
844#ifdef ESPHOME_DEBUG_SCHEDULER
845 ESP_LOGD(TAG,
"Recycled item to pool (pool size now: %zu)", this->scheduler_item_pool_.size());
848#ifdef ESPHOME_DEBUG_SCHEDULER
849 ESP_LOGD(TAG,
"Pool full (size: %zu), deleting item", this->scheduler_item_pool_.size());
855#ifdef ESPHOME_DEBUG_SCHEDULER
856void Scheduler::debug_log_timer_(
const SchedulerItem *item, NameType name_type,
const char *static_name,
857 uint32_t hash_or_id, SchedulerItem::Type
type, uint32_t
delay, uint64_t now) {
859 if (name_type == NameType::STATIC_STRING && static_name !=
nullptr) {
860 validate_static_string(static_name);
864 SchedulerNameLog name_log;
865 const char *type_str = (
type == SchedulerItem::TIMEOUT) ?
"timeout" :
"interval";
866 if (
type == SchedulerItem::TIMEOUT) {
867 ESP_LOGD(TAG,
"set_%s(name='%s/%s', %s=%" PRIu32
")", type_str, LOG_STR_ARG(item->get_source()),
868 name_log.format(name_type, static_name, hash_or_id), type_str,
delay);
870 ESP_LOGD(TAG,
"set_%s(name='%s/%s', %s=%" PRIu32
", offset=%" PRIu32
")", type_str, LOG_STR_ARG(item->get_source()),
871 name_log.format(name_type, static_name, hash_or_id), type_str,
delay,
872 static_cast<uint32_t>(item->get_next_execution() - now));
879std::unique_ptr<Scheduler::SchedulerItem> Scheduler::get_item_from_pool_locked_() {
880 std::unique_ptr<SchedulerItem> item;
881 if (!this->scheduler_item_pool_.empty()) {
882 item = std::move(this->scheduler_item_pool_.back());
883 this->scheduler_item_pool_.pop_back();
884#ifdef ESPHOME_DEBUG_SCHEDULER
885 ESP_LOGD(TAG,
"Reused item from pool (pool size now: %zu)", this->scheduler_item_pool_.size());
888 item = make_unique<SchedulerItem>();
889#ifdef ESPHOME_DEBUG_SCHEDULER
890 ESP_LOGD(TAG,
"Allocated new item (pool empty)");
void set_current_component(Component *component)
const Component * component
Providing packet encoding functions for exchanging data with a remote host.
float random_float()
Return a random float between 0 and 1.
void retry_handler(const std::shared_ptr< RetryArgs > &args)
void IRAM_ATTR HOT delay(uint32_t ms)
uint32_t IRAM_ATTR HOT millis()
Application App
Global storage of Application pointer - only one Application can exist.
constexpr uint32_t fnv1a_hash(const char *str)
Calculate a FNV-1a hash of str.