Skip to content

Commit 9203c47

Browse files
committed
Fix #364 Introduce cleanup() function
This function is similar to `cleanupClients(N)` for WebSocket except that it only cleanups internal resources. This "book-keeping" function has to be called in the loop(). This is a non-elegant attempt to fix issue #364
1 parent 9e94769 commit 9203c47

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

src/AsyncEventSource.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,21 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient *client) {
370370
#ifdef ESP32
371371
std::lock_guard<std::recursive_mutex> lock(_client_queue_lock);
372372
#endif
373-
_clients.emplace_back(client);
373+
374+
// find first unique_ptr with nullptr and reuse it
375+
bool reused = false;
376+
for (auto &c : _clients) {
377+
if (c.get() == nullptr) {
378+
c.reset(client);
379+
reused = true;
380+
break;
381+
}
382+
}
383+
384+
if (!reused) {
385+
_clients.emplace_back(client);
386+
}
387+
374388
if (_connectcb) {
375389
_connectcb(client);
376390
}
@@ -387,7 +401,7 @@ void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient *client) {
387401
#endif
388402
for (auto i = _clients.begin(); i != _clients.end(); ++i) {
389403
if (i->get() == client) {
390-
_clients.erase(i);
404+
i->reset(); // reset the unique_ptr but do not remove the list entry yet to keep other iterators valid
391405
break;
392406
}
393407
}
@@ -402,7 +416,7 @@ void AsyncEventSource::close() {
402416
std::lock_guard<std::recursive_mutex> lock(_client_queue_lock);
403417
#endif
404418
for (const auto &c : _clients) {
405-
if (c->connected()) {
419+
if (c.get() != nullptr && c->connected()) {
406420
/**
407421
* @brief: Fix self-deadlock by using recursive_mutex instead.
408422
* Due to c->close() shall call the callback function _onDisconnect()
@@ -413,6 +427,17 @@ void AsyncEventSource::close() {
413427
}
414428
}
415429

430+
void AsyncEventSource::cleanup() {
431+
#ifdef ESP32
432+
std::lock_guard<std::recursive_mutex> lock(_client_queue_lock);
433+
#endif
434+
435+
// resize the list to remove unique_ptr with nullptr
436+
_clients.remove_if([](const std::unique_ptr<AsyncEventSourceClient> &c) {
437+
return c.get() == nullptr;
438+
});
439+
}
440+
416441
// pmb fix
417442
size_t AsyncEventSource::avgPacketsWaiting() const {
418443
size_t aql = 0;
@@ -421,7 +446,7 @@ size_t AsyncEventSource::avgPacketsWaiting() const {
421446
std::lock_guard<std::recursive_mutex> lock(_client_queue_lock);
422447
#endif
423448
for (const auto &c : _clients) {
424-
if (c->connected()) {
449+
if (c.get() != nullptr && c->connected()) {
425450
aql += c->packetsWaiting();
426451
++nConnectedClients;
427452
}
@@ -437,7 +462,7 @@ AsyncEventSource::SendStatus AsyncEventSource::send(const char *message, const c
437462
size_t hits = 0;
438463
size_t miss = 0;
439464
for (const auto &c : _clients) {
440-
if (c->connected()) {
465+
if (c.get() != nullptr && c->connected()) {
441466
if (c->write(shared_msg)) {
442467
++hits;
443468
} else {
@@ -454,7 +479,7 @@ size_t AsyncEventSource::count() const {
454479
#endif
455480
size_t n_clients{0};
456481
for (const auto &i : _clients) {
457-
if (i->connected()) {
482+
if (i.get() != nullptr && i->connected()) {
458483
++n_clients;
459484
}
460485
}
@@ -476,7 +501,7 @@ void AsyncEventSource::_adjust_inflight_window() {
476501
if (clientCount) {
477502
size_t inflight = SSE_MAX_INFLIGH / clientCount;
478503
for (const auto &c : _clients) {
479-
if (c->connected()) {
504+
if (c.get() != nullptr && c->connected()) {
480505
c->set_max_inflight_bytes(inflight);
481506
}
482507
}

src/AsyncEventSource.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ class AsyncEventSource : public AsyncWebHandler {
272272
// close all connected clients
273273
void close();
274274

275+
// Cleanup internal resources.
276+
// Has to be called periodically in the loop
277+
void cleanup();
278+
275279
/**
276280
* @brief set on-connect callback for the client
277281
* used to deliver messages to client on first connect

0 commit comments

Comments
 (0)