mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 23:21:54 +00:00 
			
		
		
		
	explain why its safe
This commit is contained in:
		| @@ -94,13 +94,15 @@ class Scheduler { | |||||||
|       char *dynamic_name;       // For allocated strings |       char *dynamic_name;       // For allocated strings | ||||||
|     } name_; |     } name_; | ||||||
|     uint32_t interval; |     uint32_t interval; | ||||||
|     // Split 64-bit time to handle millis() rollover. The scheduler combines the 32-bit millis() |     // Split time to handle millis() rollover. The scheduler combines the 32-bit millis() | ||||||
|     // with a 16-bit rollover counter to create a 64-bit time that won't roll over for |     // with a 16-bit rollover counter to create a 48-bit time space (stored as 64-bit | ||||||
|     // billions of years. This ensures correct scheduling even when devices run for months. |     // for compatibility). With 49.7 days per 32-bit rollover, the 16-bit counter | ||||||
|     // Split into two fields for better memory alignment on 32-bit systems. |     // supports 49.7 days × 65536 = ~8900 years. This ensures correct scheduling | ||||||
|     uint32_t next_execution_low_;  // Lower 32 bits of next execution time |     // even when devices run for months. Split into two fields for better memory | ||||||
|  |     // alignment on 32-bit systems. | ||||||
|  |     uint32_t next_execution_low_;  // Lower 32 bits of execution time (millis value) | ||||||
|     std::function<void()> callback; |     std::function<void()> callback; | ||||||
|     uint16_t next_execution_high_;  // Upper 16 bits of next execution time |     uint16_t next_execution_high_;  // Upper 16 bits (millis_major counter) | ||||||
|  |  | ||||||
| #ifdef ESPHOME_THREAD_MULTI_ATOMICS | #ifdef ESPHOME_THREAD_MULTI_ATOMICS | ||||||
|     // Multi-threaded with atomics: use atomic for lock-free access |     // Multi-threaded with atomics: use atomic for lock-free access | ||||||
| @@ -186,12 +188,17 @@ class Scheduler { | |||||||
|     static bool cmp(const std::unique_ptr<SchedulerItem> &a, const std::unique_ptr<SchedulerItem> &b); |     static bool cmp(const std::unique_ptr<SchedulerItem> &a, const std::unique_ptr<SchedulerItem> &b); | ||||||
|  |  | ||||||
|     // Helper methods to work with split execution time (constexpr for optimization) |     // Helper methods to work with split execution time (constexpr for optimization) | ||||||
|  |     // Note: We use 48 bits total (32 + 16), stored in a 64-bit value for API compatibility. | ||||||
|  |     // The upper 16 bits of the 64-bit value are always zero, which is fine since | ||||||
|  |     // millis_major_ is also 16 bits and they must match. | ||||||
|     constexpr uint64_t get_next_execution() const { |     constexpr uint64_t get_next_execution() const { | ||||||
|       return (static_cast<uint64_t>(next_execution_high_) << 32) | next_execution_low_; |       return (static_cast<uint64_t>(next_execution_high_) << 32) | next_execution_low_; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     constexpr void set_next_execution(uint64_t value) { |     constexpr void set_next_execution(uint64_t value) { | ||||||
|       next_execution_low_ = static_cast<uint32_t>(value); |       next_execution_low_ = static_cast<uint32_t>(value); | ||||||
|  |       // Cast to uint16_t intentionally truncates to lower 16 bits of the upper 32 bits. | ||||||
|  |       // This is correct because millis_major_ that creates these values is also 16 bits. | ||||||
|       next_execution_high_ = static_cast<uint16_t>(value >> 32); |       next_execution_high_ = static_cast<uint16_t>(value >> 32); | ||||||
|     } |     } | ||||||
|     constexpr const char *get_type_str() const { return (type == TIMEOUT) ? "timeout" : "interval"; } |     constexpr const char *get_type_str() const { return (type == TIMEOUT) ? "timeout" : "interval"; } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user