mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge branch 'scheduler_copy' into integration
This commit is contained in:
		| @@ -68,6 +68,10 @@ bool Component::cancel_interval(const std::string &name) {  // NOLINT | |||||||
|   return App.scheduler.cancel_interval(this, name); |   return App.scheduler.cancel_interval(this, name); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool Component::cancel_interval(const char *name) {  // NOLINT | ||||||
|  |   return App.scheduler.cancel_interval(this, name); | ||||||
|  | } | ||||||
|  |  | ||||||
| void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, | void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, | ||||||
|                           std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) {  // NOLINT |                           std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) {  // NOLINT | ||||||
|   App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); |   App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); | ||||||
| @@ -89,6 +93,10 @@ bool Component::cancel_timeout(const std::string &name) {  // NOLINT | |||||||
|   return App.scheduler.cancel_timeout(this, name); |   return App.scheduler.cancel_timeout(this, name); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool Component::cancel_timeout(const char *name) {  // NOLINT | ||||||
|  |   return App.scheduler.cancel_timeout(this, name); | ||||||
|  | } | ||||||
|  |  | ||||||
| void Component::call_loop() { this->loop(); } | void Component::call_loop() { this->loop(); } | ||||||
| void Component::call_setup() { this->setup(); } | void Component::call_setup() { this->setup(); } | ||||||
| void Component::call_dump_config() { | void Component::call_dump_config() { | ||||||
|   | |||||||
| @@ -285,6 +285,7 @@ class Component { | |||||||
|    * @return Whether an interval functions was deleted. |    * @return Whether an interval functions was deleted. | ||||||
|    */ |    */ | ||||||
|   bool cancel_interval(const std::string &name);  // NOLINT |   bool cancel_interval(const std::string &name);  // NOLINT | ||||||
|  |   bool cancel_interval(const char *name);         // NOLINT | ||||||
|  |  | ||||||
|   /** Set an retry function with a unique name. Empty name means no cancelling possible. |   /** Set an retry function with a unique name. Empty name means no cancelling possible. | ||||||
|    * |    * | ||||||
| @@ -369,6 +370,7 @@ class Component { | |||||||
|    * @return Whether a timeout functions was deleted. |    * @return Whether a timeout functions was deleted. | ||||||
|    */ |    */ | ||||||
|   bool cancel_timeout(const std::string &name);  // NOLINT |   bool cancel_timeout(const std::string &name);  // NOLINT | ||||||
|  |   bool cancel_timeout(const char *name);         // NOLINT | ||||||
|  |  | ||||||
|   /** Defer a callback to the next loop() call. |   /** Defer a callback to the next loop() call. | ||||||
|    * |    * | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <cinttypes> | #include <cinttypes> | ||||||
|  | #include <cstring> | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
|  |  | ||||||
| @@ -124,6 +125,9 @@ void HOT Scheduler::set_timeout(Component *component, const std::string &name, u | |||||||
| bool HOT Scheduler::cancel_timeout(Component *component, const std::string &name) { | bool HOT Scheduler::cancel_timeout(Component *component, const std::string &name) { | ||||||
|   return this->cancel_item_(component, name, SchedulerItem::TIMEOUT); |   return this->cancel_item_(component, name, SchedulerItem::TIMEOUT); | ||||||
| } | } | ||||||
|  | bool HOT Scheduler::cancel_timeout(Component *component, const char *name) { | ||||||
|  |   return this->cancel_item_(component, name, SchedulerItem::TIMEOUT); | ||||||
|  | } | ||||||
| void HOT Scheduler::set_interval(Component *component, const std::string &name, uint32_t interval, | void HOT Scheduler::set_interval(Component *component, const std::string &name, uint32_t interval, | ||||||
|                                  std::function<void()> func) { |                                  std::function<void()> func) { | ||||||
|   this->set_timer_common_(component, SchedulerItem::INTERVAL, false, &name, interval, std::move(func)); |   this->set_timer_common_(component, SchedulerItem::INTERVAL, false, &name, interval, std::move(func)); | ||||||
| @@ -136,6 +140,9 @@ void HOT Scheduler::set_interval(Component *component, const char *name, uint32_ | |||||||
| bool HOT Scheduler::cancel_interval(Component *component, const std::string &name) { | bool HOT Scheduler::cancel_interval(Component *component, const std::string &name) { | ||||||
|   return this->cancel_item_(component, name, SchedulerItem::INTERVAL); |   return this->cancel_item_(component, name, SchedulerItem::INTERVAL); | ||||||
| } | } | ||||||
|  | bool HOT Scheduler::cancel_interval(Component *component, const char *name) { | ||||||
|  |   return this->cancel_item_(component, name, SchedulerItem::INTERVAL); | ||||||
|  | } | ||||||
|  |  | ||||||
| struct RetryArgs { | struct RetryArgs { | ||||||
|   std::function<RetryResult(uint8_t)> func; |   std::function<RetryResult(uint8_t)> func; | ||||||
| @@ -357,13 +364,25 @@ void HOT Scheduler::push_(std::unique_ptr<Scheduler::SchedulerItem> item) { | |||||||
|   LockGuard guard{this->lock_}; |   LockGuard guard{this->lock_}; | ||||||
|   this->to_add_.push_back(std::move(item)); |   this->to_add_.push_back(std::move(item)); | ||||||
| } | } | ||||||
| bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, Scheduler::SchedulerItem::Type type) { | // Common implementation for cancel operations | ||||||
|  | bool HOT Scheduler::cancel_item_common_(Component *component, bool is_static_string, const void *name_ptr, | ||||||
|  |                                         SchedulerItem::Type type) { | ||||||
|  |   // Get the name as const char* | ||||||
|  |   const char *name_cstr = | ||||||
|  |       is_static_string ? static_cast<const char *>(name_ptr) : static_cast<const std::string *>(name_ptr)->c_str(); | ||||||
|  |  | ||||||
|  |   // Handle null or empty names | ||||||
|  |   if (name_cstr == nullptr) | ||||||
|  |     return false; | ||||||
|  |  | ||||||
|   // obtain lock because this function iterates and can be called from non-loop task context |   // obtain lock because this function iterates and can be called from non-loop task context | ||||||
|   LockGuard guard{this->lock_}; |   LockGuard guard{this->lock_}; | ||||||
|   bool ret = false; |   bool ret = false; | ||||||
|  |  | ||||||
|   for (auto &it : this->items_) { |   for (auto &it : this->items_) { | ||||||
|     const char *item_name = it->get_name(); |     const char *item_name = it->get_name(); | ||||||
|     if (it->component == component && item_name != nullptr && name == item_name && it->type == type && !it->remove) { |     if (it->component == component && item_name != nullptr && strcmp(name_cstr, item_name) == 0 && it->type == type && | ||||||
|  |         !it->remove) { | ||||||
|       to_remove_++; |       to_remove_++; | ||||||
|       it->remove = true; |       it->remove = true; | ||||||
|       ret = true; |       ret = true; | ||||||
| @@ -371,7 +390,7 @@ bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, | |||||||
|   } |   } | ||||||
|   for (auto &it : this->to_add_) { |   for (auto &it : this->to_add_) { | ||||||
|     const char *item_name = it->get_name(); |     const char *item_name = it->get_name(); | ||||||
|     if (it->component == component && item_name != nullptr && name == item_name && it->type == type) { |     if (it->component == component && item_name != nullptr && strcmp(name_cstr, item_name) == 0 && it->type == type) { | ||||||
|       it->remove = true; |       it->remove = true; | ||||||
|       ret = true; |       ret = true; | ||||||
|     } |     } | ||||||
| @@ -379,6 +398,15 @@ bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, | |||||||
|  |  | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, Scheduler::SchedulerItem::Type type) { | ||||||
|  |   return this->cancel_item_common_(component, false, &name, type); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool HOT Scheduler::cancel_item_(Component *component, const char *name, SchedulerItem::Type type) { | ||||||
|  |   return this->cancel_item_common_(component, true, name, type); | ||||||
|  | } | ||||||
|  |  | ||||||
| uint64_t Scheduler::millis_() { | uint64_t Scheduler::millis_() { | ||||||
|   // Get the current 32-bit millis value |   // Get the current 32-bit millis value | ||||||
|   const uint32_t now = millis(); |   const uint32_t now = millis(); | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ class Scheduler { | |||||||
|   void set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func); |   void set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func); | ||||||
|  |  | ||||||
|   bool cancel_timeout(Component *component, const std::string &name); |   bool cancel_timeout(Component *component, const std::string &name); | ||||||
|  |   bool cancel_timeout(Component *component, const char *name); | ||||||
|  |  | ||||||
|   void set_interval(Component *component, const std::string &name, uint32_t interval, std::function<void()> func); |   void set_interval(Component *component, const std::string &name, uint32_t interval, std::function<void()> func); | ||||||
|  |  | ||||||
| @@ -44,6 +45,7 @@ class Scheduler { | |||||||
|   void set_interval(Component *component, const char *name, uint32_t interval, std::function<void()> func); |   void set_interval(Component *component, const char *name, uint32_t interval, std::function<void()> func); | ||||||
|  |  | ||||||
|   bool cancel_interval(Component *component, const std::string &name); |   bool cancel_interval(Component *component, const std::string &name); | ||||||
|  |   bool cancel_interval(Component *component, const char *name); | ||||||
|   void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, |   void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, | ||||||
|                  std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f); |                  std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f); | ||||||
|   bool cancel_retry(Component *component, const std::string &name); |   bool cancel_retry(Component *component, const std::string &name); | ||||||
| @@ -137,7 +139,12 @@ class Scheduler { | |||||||
|   void cleanup_(); |   void cleanup_(); | ||||||
|   void pop_raw_(); |   void pop_raw_(); | ||||||
|   void push_(std::unique_ptr<SchedulerItem> item); |   void push_(std::unique_ptr<SchedulerItem> item); | ||||||
|  |   // Common implementation for cancel operations | ||||||
|  |   bool cancel_item_common_(Component *component, bool is_static_string, const void *name_ptr, SchedulerItem::Type type); | ||||||
|  |  | ||||||
|   bool cancel_item_(Component *component, const std::string &name, SchedulerItem::Type type); |   bool cancel_item_(Component *component, const std::string &name, SchedulerItem::Type type); | ||||||
|  |   bool cancel_item_(Component *component, const char *name, SchedulerItem::Type type); | ||||||
|  |  | ||||||
|   bool empty_() { |   bool empty_() { | ||||||
|     this->cleanup_(); |     this->cleanup_(); | ||||||
|     return this->items_.empty(); |     return this->items_.empty(); | ||||||
|   | |||||||
| @@ -111,7 +111,7 @@ async def test_scheduler_string_test( | |||||||
|         try: |         try: | ||||||
|             await asyncio.wait_for(static_interval_fired.wait(), timeout=1.0) |             await asyncio.wait_for(static_interval_fired.wait(), timeout=1.0) | ||||||
|         except asyncio.TimeoutError: |         except asyncio.TimeoutError: | ||||||
|             pytest.fail("Static interval did not fire within 1 seconds") |             pytest.fail("Static interval did not fire within 1 second") | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             await asyncio.wait_for(static_interval_cancelled.wait(), timeout=2.0) |             await asyncio.wait_for(static_interval_cancelled.wait(), timeout=2.0) | ||||||
| @@ -127,7 +127,7 @@ async def test_scheduler_string_test( | |||||||
|         try: |         try: | ||||||
|             await asyncio.wait_for(dynamic_timeout_fired.wait(), timeout=1.0) |             await asyncio.wait_for(dynamic_timeout_fired.wait(), timeout=1.0) | ||||||
|         except asyncio.TimeoutError: |         except asyncio.TimeoutError: | ||||||
|             pytest.fail("Dynamic timeout did not fire within 1 seconds") |             pytest.fail("Dynamic timeout did not fire within 1 second") | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             await asyncio.wait_for(dynamic_interval_fired.wait(), timeout=1.5) |             await asyncio.wait_for(dynamic_interval_fired.wait(), timeout=1.5) | ||||||
| @@ -138,7 +138,7 @@ async def test_scheduler_string_test( | |||||||
|         try: |         try: | ||||||
|             await asyncio.wait_for(cancel_test_done.wait(), timeout=1.0) |             await asyncio.wait_for(cancel_test_done.wait(), timeout=1.0) | ||||||
|         except asyncio.TimeoutError: |         except asyncio.TimeoutError: | ||||||
|             pytest.fail("Cancel test did not complete within 1 seconds") |             pytest.fail("Cancel test did not complete within 1 second") | ||||||
|  |  | ||||||
|         # Wait for final results |         # Wait for final results | ||||||
|         try: |         try: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user