mirror of
https://github.com/esphome/esphome.git
synced 2025-10-20 10:43:48 +01:00
[web_server_idf] Use std::vector instead of std::set for SSE sessions (#11233)
This commit is contained in:
@@ -380,24 +380,25 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request) {
|
|||||||
if (this->on_connect_) {
|
if (this->on_connect_) {
|
||||||
this->on_connect_(rsp);
|
this->on_connect_(rsp);
|
||||||
}
|
}
|
||||||
this->sessions_.insert(rsp);
|
this->sessions_.push_back(rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSource::loop() {
|
void AsyncEventSource::loop() {
|
||||||
// Clean up dead sessions safely
|
// Clean up dead sessions safely
|
||||||
// This follows the ESP-IDF pattern where free_ctx marks resources as dead
|
// This follows the ESP-IDF pattern where free_ctx marks resources as dead
|
||||||
// and the main loop handles the actual cleanup to avoid race conditions
|
// and the main loop handles the actual cleanup to avoid race conditions
|
||||||
auto it = this->sessions_.begin();
|
for (size_t i = 0; i < this->sessions_.size();) {
|
||||||
while (it != this->sessions_.end()) {
|
auto *ses = this->sessions_[i];
|
||||||
auto *ses = *it;
|
|
||||||
// If the session has a dead socket (marked by destroy callback)
|
// If the session has a dead socket (marked by destroy callback)
|
||||||
if (ses->fd_.load() == 0) {
|
if (ses->fd_.load() == 0) {
|
||||||
ESP_LOGD(TAG, "Removing dead event source session");
|
ESP_LOGD(TAG, "Removing dead event source session");
|
||||||
it = this->sessions_.erase(it);
|
|
||||||
delete ses; // NOLINT(cppcoreguidelines-owning-memory)
|
delete ses; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
// Remove by swapping with last element (O(1) removal, order doesn't matter for sessions)
|
||||||
|
this->sessions_[i] = this->sessions_.back();
|
||||||
|
this->sessions_.pop_back();
|
||||||
} else {
|
} else {
|
||||||
ses->loop();
|
ses->loop();
|
||||||
++it;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,6 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -315,7 +314,10 @@ class AsyncEventSource : public AsyncWebHandler {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string url_;
|
std::string url_;
|
||||||
std::set<AsyncEventSourceResponse *> sessions_;
|
// Use vector instead of set: SSE sessions are typically 1-5 connections (browsers, dashboards).
|
||||||
|
// Linear search is faster than red-black tree overhead for this small dataset.
|
||||||
|
// Only operations needed: add session, remove session, iterate sessions - no need for sorted order.
|
||||||
|
std::vector<AsyncEventSourceResponse *> sessions_;
|
||||||
connect_handler_t on_connect_{};
|
connect_handler_t on_connect_{};
|
||||||
esphome::web_server::WebServer *web_server_;
|
esphome::web_server::WebServer *web_server_;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user