From c789d80ce5b44fb07e5510b842a4e63d37a60c72 Mon Sep 17 00:00:00 2001 From: Will Miles Date: Mon, 12 Feb 2024 08:59:50 -0500 Subject: [PATCH] LockedJsonResponse: Release early if possible Release the json buffer lock as soon as we've finished serializing. This should slightly reduce the number of lock collisions as the response class isn't destructed until after the last packet is ack'd. --- wled00/json.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index b4bb38715..1e05e1d66 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1023,14 +1023,26 @@ void serializeModeNames(JsonArray arr) // Global buffer locking response helper class (to make sure lock is released when AsyncJsonResponse is destroyed) class LockedJsonResponse: public AsyncJsonResponse { + bool _holding_lock; public: // WARNING: constructor assumes requestJSONBufferLock() was successfully acquired externally/prior to constructing the instance // Not a good practice with C++. Unfortunately AsyncJsonResponse only has 2 constructors - for dynamic buffer or existing buffer, // with existing buffer it clears its content during construction // if the lock was not acquired (using JSONBufferGuard class) previous implementation still cleared existing buffer - inline LockedJsonResponse(JsonDocument *doc, bool isArray) : AsyncJsonResponse(doc, isArray) {}; + inline LockedJsonResponse(JsonDocument* doc, bool isArray) : AsyncJsonResponse(doc, isArray), _holding_lock(true) {}; + + virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) { + size_t result = AsyncJsonResponse::_fillBuffer(buf, maxLen); + // Release lock as soon as we're done filling content + if (((result + _sentLength) >= (_contentLength)) && _holding_lock) { + releaseJSONBufferLock(); + _holding_lock = false; + } + return result; + } + // destructor will remove JSON buffer lock when response is destroyed in AsyncWebServer - virtual ~LockedJsonResponse() { releaseJSONBufferLock(); }; + virtual ~LockedJsonResponse() { if (_holding_lock) releaseJSONBufferLock(); }; }; void serveJson(AsyncWebServerRequest* request)