From aea43f98d10769f78118082921ca7df406fc83a9 Mon Sep 17 00:00:00 2001 From: matt123p Date: Thu, 12 Sep 2019 17:56:13 +0100 Subject: [PATCH] Add thread locking to improve stability. (#585) * Add thread locking to improve stability. * Do not use thread locking with the ESP8266, but instead use an empty placeholder class that can be used to implement locking at a later date. --- src/AsyncWebSocket.cpp | 4 ++ src/AsyncWebSocket.h | 4 ++ src/AsyncWebSynchronization.h | 87 +++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 src/AsyncWebSynchronization.h diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index 9bd037a..3f2ad13 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -1197,6 +1197,7 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size) { AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size); if (buffer) { + AsyncWebLockGuard l(_lock); _buffers.add(buffer); } return buffer; @@ -1207,6 +1208,7 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size); if (buffer) { + AsyncWebLockGuard l(_lock); _buffers.add(buffer); } @@ -1215,6 +1217,8 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t void AsyncWebSocket::_cleanBuffers() { + AsyncWebLockGuard l(_lock); + for(AsyncWebSocketMessageBuffer * c: _buffers){ if(c && c->canDelete()){ _buffers.remove(c); diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 2a47a0d..8e2954e 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -31,6 +31,8 @@ #endif #include +#include "AsyncWebSynchronization.h" + #ifdef ESP8266 #include #endif @@ -236,6 +238,8 @@ class AsyncWebSocket: public AsyncWebHandler { uint32_t _cNextId; AwsEventHandler _eventHandler; bool _enabled; + AsyncWebLock _lock; + public: AsyncWebSocket(const String& url); ~AsyncWebSocket(); diff --git a/src/AsyncWebSynchronization.h b/src/AsyncWebSynchronization.h new file mode 100644 index 0000000..f36c52d --- /dev/null +++ b/src/AsyncWebSynchronization.h @@ -0,0 +1,87 @@ +#ifndef ASYNCWEBSYNCHRONIZATION_H_ +#define ASYNCWEBSYNCHRONIZATION_H_ + +// Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default + +#include + +#ifdef ESP32 + +// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore +class AsyncWebLock +{ +private: + SemaphoreHandle_t _lock; + mutable void *_lockedBy; + +public: + AsyncWebLock() { + _lock = xSemaphoreCreateBinary(); + _lockedBy = NULL; + xSemaphoreGive(_lock); + } + + ~AsyncWebLock() { + vSemaphoreDelete(_lock); + } + + bool lock() const { + extern void *pxCurrentTCB; + if (_lockedBy != pxCurrentTCB) { + xSemaphoreTake(_lock, portMAX_DELAY); + _lockedBy = pxCurrentTCB; + return true; + } + return false; + } + + void unlock() const { + _lockedBy = NULL; + xSemaphoreGive(_lock); + } +}; + +#else + +// This is the 8266 version of the Sync Lock which is currently unimplemented +class AsyncWebLock +{ + +public: + AsyncWebLock() { + } + + ~AsyncWebLock() { + } + + bool lock() const { + return false; + } + + void unlock() const { + } +}; +#endif + +class AsyncWebLockGuard +{ +private: + const AsyncWebLock *_lock; + +public: + AsyncWebLockGuard(const AsyncWebLock &l) { + if (l.lock()) { + _lock = &l; + } else { + _lock = NULL; + } + } + + ~AsyncWebLockGuard() { + if (_lock) { + _lock->unlock(); + } + } +}; + +#endif // ASYNCWEBSYNCHRONIZATION_H_ \ No newline at end of file