From d9b0df94e2a344b05bac88270a162b8e25f86ec5 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 e63a09ee..af8ed89e 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1022,14 +1022,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)