mirror of
https://github.com/esphome/esphome.git
synced 2025-07-29 14:46:40 +00:00
Always perform select() when loop duration exceeds interval (#9058)
This commit is contained in:
parent
7a5c9a821a
commit
592446e430
@ -117,7 +117,9 @@ void Application::loop() {
|
|||||||
// Use the last component's end time instead of calling millis() again
|
// Use the last component's end time instead of calling millis() again
|
||||||
auto elapsed = last_op_end_time - this->last_loop_;
|
auto elapsed = last_op_end_time - this->last_loop_;
|
||||||
if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) {
|
if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) {
|
||||||
yield();
|
// Even if we overran the loop interval, we still need to select()
|
||||||
|
// to know if any sockets have data ready
|
||||||
|
this->yield_with_select_(0);
|
||||||
} else {
|
} else {
|
||||||
uint32_t delay_time = this->loop_interval_ - elapsed;
|
uint32_t delay_time = this->loop_interval_ - elapsed;
|
||||||
uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
|
uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
|
||||||
@ -126,7 +128,7 @@ void Application::loop() {
|
|||||||
next_schedule = std::max(next_schedule, delay_time / 2);
|
next_schedule = std::max(next_schedule, delay_time / 2);
|
||||||
delay_time = std::min(next_schedule, delay_time);
|
delay_time = std::min(next_schedule, delay_time);
|
||||||
|
|
||||||
this->delay_with_select_(delay_time);
|
this->yield_with_select_(delay_time);
|
||||||
}
|
}
|
||||||
this->last_loop_ = last_op_end_time;
|
this->last_loop_ = last_op_end_time;
|
||||||
|
|
||||||
@ -215,7 +217,7 @@ void Application::teardown_components(uint32_t timeout_ms) {
|
|||||||
|
|
||||||
// Give some time for I/O operations if components are still pending
|
// Give some time for I/O operations if components are still pending
|
||||||
if (!pending_components.empty()) {
|
if (!pending_components.empty()) {
|
||||||
this->delay_with_select_(1);
|
this->yield_with_select_(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update time for next iteration
|
// Update time for next iteration
|
||||||
@ -293,8 +295,6 @@ bool Application::is_socket_ready(int fd) const {
|
|||||||
// This function is thread-safe for reading the result of select()
|
// This function is thread-safe for reading the result of select()
|
||||||
// However, it should only be called after select() has been executed in the main loop
|
// However, it should only be called after select() has been executed in the main loop
|
||||||
// The read_fds_ is only modified by select() in the main loop
|
// The read_fds_ is only modified by select() in the main loop
|
||||||
if (HighFrequencyLoopRequester::is_high_frequency())
|
|
||||||
return true; // fd sets via select are not updated in high frequency looping - so force true fallback behavior
|
|
||||||
if (fd < 0 || fd >= FD_SETSIZE)
|
if (fd < 0 || fd >= FD_SETSIZE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -302,7 +302,9 @@ bool Application::is_socket_ready(int fd) const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Application::delay_with_select_(uint32_t delay_ms) {
|
void Application::yield_with_select_(uint32_t delay_ms) {
|
||||||
|
// Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run
|
||||||
|
// since select() with 0 timeout only polls without yielding.
|
||||||
#ifdef USE_SOCKET_SELECT_SUPPORT
|
#ifdef USE_SOCKET_SELECT_SUPPORT
|
||||||
if (!this->socket_fds_.empty()) {
|
if (!this->socket_fds_.empty()) {
|
||||||
// Update fd_set if socket list has changed
|
// Update fd_set if socket list has changed
|
||||||
@ -340,6 +342,10 @@ void Application::delay_with_select_(uint32_t delay_ms) {
|
|||||||
ESP_LOGW(TAG, "select() failed with errno %d", errno);
|
ESP_LOGW(TAG, "select() failed with errno %d", errno);
|
||||||
delay(delay_ms);
|
delay(delay_ms);
|
||||||
}
|
}
|
||||||
|
// When delay_ms is 0, we need to yield since select(0) doesn't yield
|
||||||
|
if (delay_ms == 0) {
|
||||||
|
yield();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// No sockets registered, use regular delay
|
// No sockets registered, use regular delay
|
||||||
delay(delay_ms);
|
delay(delay_ms);
|
||||||
|
@ -575,7 +575,7 @@ class Application {
|
|||||||
void feed_wdt_arch_();
|
void feed_wdt_arch_();
|
||||||
|
|
||||||
/// Perform a delay while also monitoring socket file descriptors for readiness
|
/// Perform a delay while also monitoring socket file descriptors for readiness
|
||||||
void delay_with_select_(uint32_t delay_ms);
|
void yield_with_select_(uint32_t delay_ms);
|
||||||
|
|
||||||
std::vector<Component *> components_{};
|
std::vector<Component *> components_{};
|
||||||
std::vector<Component *> looping_components_{};
|
std::vector<Component *> looping_components_{};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user