mirror of
https://github.com/me-no-dev/ESPAsyncWebServer.git
synced 2025-08-07 14:44:38 +02:00
replace self-implemented mutex structures with std:mutex
Use STL's platform implementation for mutex locks
This commit is contained in:
committed by
Mathieu Carbou
parent
16fd203198
commit
d614ccde91
@@ -18,10 +18,10 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "AsyncEventSource.h"
|
|
||||||
#ifndef ESP8266
|
#ifndef ESP8266
|
||||||
#include <rom/ets_sys.h>
|
#include <rom/ets_sys.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "AsyncEventSource.h"
|
||||||
|
|
||||||
static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
||||||
String ev;
|
String ev;
|
||||||
@@ -177,9 +177,10 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncEventSourceClient::~AsyncEventSourceClient(){
|
AsyncEventSourceClient::~AsyncEventSourceClient(){
|
||||||
_lockmq.lock();
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
|
#endif
|
||||||
_messageQueue.free();
|
_messageQueue.free();
|
||||||
_lockmq.unlock();
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +191,10 @@ void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage)
|
|||||||
delete dataMessage;
|
delete dataMessage;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef ESP32
|
||||||
//length() is not thread-safe, thus acquiring the lock before this call..
|
//length() is not thread-safe, thus acquiring the lock before this call..
|
||||||
_lockmq.lock();
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
|
#endif
|
||||||
if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){
|
if(_messageQueue.length() >= SSE_MAX_QUEUED_MESSAGES){
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
ets_printf(String(F("ERROR: Too many messages queued\n")).c_str());
|
ets_printf(String(F("ERROR: Too many messages queued\n")).c_str());
|
||||||
@@ -206,27 +209,29 @@ void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage)
|
|||||||
_runQueue();
|
_runQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_lockmq.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
|
void AsyncEventSourceClient::_onAck(size_t len, uint32_t time){
|
||||||
|
#ifdef ESP32
|
||||||
// Same here, acquiring the lock early
|
// Same here, acquiring the lock early
|
||||||
_lockmq.lock();
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
|
#endif
|
||||||
while(len && !_messageQueue.isEmpty()){
|
while(len && !_messageQueue.isEmpty()){
|
||||||
len = _messageQueue.front()->ack(len, time);
|
len = _messageQueue.front()->ack(len, time);
|
||||||
if(_messageQueue.front()->finished())
|
if(_messageQueue.front()->finished())
|
||||||
_messageQueue.remove(_messageQueue.front());
|
_messageQueue.remove(_messageQueue.front());
|
||||||
}
|
}
|
||||||
_runQueue();
|
_runQueue();
|
||||||
_lockmq.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSourceClient::_onPoll(){
|
void AsyncEventSourceClient::_onPoll(){
|
||||||
_lockmq.lock();
|
#ifdef ESP32
|
||||||
|
// Same here, acquiring the lock early
|
||||||
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
|
#endif
|
||||||
if(!_messageQueue.isEmpty()){
|
if(!_messageQueue.isEmpty()){
|
||||||
_runQueue();
|
_runQueue();
|
||||||
}
|
}
|
||||||
_lockmq.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
|
void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused))){
|
||||||
@@ -253,10 +258,10 @@ void AsyncEventSourceClient::send(const char *message, const char *event, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t AsyncEventSourceClient::packetsWaiting() const {
|
size_t AsyncEventSourceClient::packetsWaiting() const {
|
||||||
size_t len;
|
#ifdef ESP32
|
||||||
_lockmq.lock();
|
std::lock_guard<std::mutex> lock(_lockmq);
|
||||||
len = _messageQueue.length();
|
#endif
|
||||||
_lockmq.unlock();
|
size_t len = _messageQueue.length();
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,14 +311,18 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient * client){
|
|||||||
client->write((const char *)temp, 2053);
|
client->write((const char *)temp, 2053);
|
||||||
free(temp);
|
free(temp);
|
||||||
}*/
|
}*/
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
_clients.add(client);
|
_clients.add(client);
|
||||||
if(_connectcb)
|
if(_connectcb)
|
||||||
_connectcb(client);
|
_connectcb(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
|
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client){
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
_clients.remove(client);
|
_clients.remove(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +330,9 @@ void AsyncEventSource::close(){
|
|||||||
// While the whole loop is not done, the linked list is locked and so the
|
// While the whole loop is not done, the linked list is locked and so the
|
||||||
// iterator should remain valid even when AsyncEventSource::_handleDisconnect()
|
// iterator should remain valid even when AsyncEventSource::_handleDisconnect()
|
||||||
// is called very early
|
// is called very early
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
for(const auto &c: _clients){
|
for(const auto &c: _clients){
|
||||||
if(c->connected())
|
if(c->connected())
|
||||||
c->close();
|
c->close();
|
||||||
@@ -332,7 +343,9 @@ void AsyncEventSource::close(){
|
|||||||
size_t AsyncEventSource::avgPacketsWaiting() const {
|
size_t AsyncEventSource::avgPacketsWaiting() const {
|
||||||
size_t aql = 0;
|
size_t aql = 0;
|
||||||
uint32_t nConnectedClients = 0;
|
uint32_t nConnectedClients = 0;
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
if (_clients.isEmpty()) {
|
if (_clients.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -348,7 +361,9 @@ size_t AsyncEventSource::avgPacketsWaiting() const {
|
|||||||
void AsyncEventSource::send(
|
void AsyncEventSource::send(
|
||||||
const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
const char *message, const char *event, uint32_t id, uint32_t reconnect){
|
||||||
String ev = generateEventMessage(message, event, id, reconnect);
|
String ev = generateEventMessage(message, event, id, reconnect);
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
for(const auto &c: _clients){
|
for(const auto &c: _clients){
|
||||||
if(c->connected()) {
|
if(c->connected()) {
|
||||||
c->write(ev.c_str(), ev.length());
|
c->write(ev.c_str(), ev.length());
|
||||||
@@ -358,7 +373,9 @@ void AsyncEventSource::send(
|
|||||||
|
|
||||||
size_t AsyncEventSource::count() const {
|
size_t AsyncEventSource::count() const {
|
||||||
size_t n_clients;
|
size_t n_clients;
|
||||||
AsyncWebLockGuard l(_client_queue_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_client_queue_lock);
|
||||||
|
#endif
|
||||||
n_clients = _clients.count_if([](AsyncEventSourceClient *c){
|
n_clients = _clients.count_if([](AsyncEventSourceClient *c){
|
||||||
return c->connected();
|
return c->connected();
|
||||||
});
|
});
|
||||||
|
@@ -22,11 +22,12 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
|
#include <mutex>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#ifndef SSE_MAX_QUEUED_MESSAGES
|
#ifndef SSE_MAX_QUEUED_MESSAGES
|
||||||
#define SSE_MAX_QUEUED_MESSAGES 32
|
#define SSE_MAX_QUEUED_MESSAGES 32
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else // esp8266
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#ifndef SSE_MAX_QUEUED_MESSAGES
|
#ifndef SSE_MAX_QUEUED_MESSAGES
|
||||||
#define SSE_MAX_QUEUED_MESSAGES 8
|
#define SSE_MAX_QUEUED_MESSAGES 8
|
||||||
@@ -35,8 +36,6 @@
|
|||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
#include "AsyncWebSynchronization.h"
|
|
||||||
|
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#include <Hash.h>
|
#include <Hash.h>
|
||||||
#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
|
#ifdef CRYPTO_HASH_h // include Hash.h from espressif framework if the first include was from the crypto library
|
||||||
@@ -81,7 +80,9 @@ class AsyncEventSourceClient {
|
|||||||
uint32_t _lastId;
|
uint32_t _lastId;
|
||||||
LinkedList<AsyncEventSourceMessage *> _messageQueue;
|
LinkedList<AsyncEventSourceMessage *> _messageQueue;
|
||||||
// ArFi 2020-08-27 for protecting/serializing _messageQueue
|
// ArFi 2020-08-27 for protecting/serializing _messageQueue
|
||||||
AsyncPlainLock _lockmq;
|
#ifdef ESP32
|
||||||
|
mutable std::mutex _lockmq;
|
||||||
|
#endif
|
||||||
void _queueMessage(AsyncEventSourceMessage *dataMessage);
|
void _queueMessage(AsyncEventSourceMessage *dataMessage);
|
||||||
void _runQueue();
|
void _runQueue();
|
||||||
|
|
||||||
@@ -109,9 +110,11 @@ class AsyncEventSource: public AsyncWebHandler {
|
|||||||
private:
|
private:
|
||||||
String _url;
|
String _url;
|
||||||
LinkedList<AsyncEventSourceClient *> _clients;
|
LinkedList<AsyncEventSourceClient *> _clients;
|
||||||
|
#ifdef ESP32
|
||||||
// Same as for individual messages, protect mutations of _clients list
|
// Same as for individual messages, protect mutations of _clients list
|
||||||
// since simultaneous access from different tasks is possible
|
// since simultaneous access from different tasks is possible
|
||||||
AsyncWebLock _client_queue_lock;
|
mutable std::mutex _client_queue_lock;
|
||||||
|
#endif
|
||||||
ArEventHandlerFunction _connectcb;
|
ArEventHandlerFunction _connectcb;
|
||||||
ArAuthorizeConnectHandler _authorizeConnectHandler;
|
ArAuthorizeConnectHandler _authorizeConnectHandler;
|
||||||
public:
|
public:
|
||||||
|
@@ -314,8 +314,9 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
|
|||||||
AsyncWebSocketClient::~AsyncWebSocketClient()
|
AsyncWebSocketClient::~AsyncWebSocketClient()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
AsyncWebLockGuard l(_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
_messageQueue.clear();
|
_messageQueue.clear();
|
||||||
_controlQueue.clear();
|
_controlQueue.clear();
|
||||||
}
|
}
|
||||||
@@ -331,7 +332,9 @@ void AsyncWebSocketClient::_clearQueue()
|
|||||||
void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
|
void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
|
||||||
_lastMessageTime = millis();
|
_lastMessageTime = millis();
|
||||||
|
|
||||||
AsyncWebLockGuard l(_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!_controlQueue.empty()) {
|
if (!_controlQueue.empty()) {
|
||||||
auto &head = _controlQueue.front();
|
auto &head = _controlQueue.front();
|
||||||
@@ -340,7 +343,6 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time){
|
|||||||
if (_status == WS_DISCONNECTING && head.opcode() == WS_DISCONNECT){
|
if (_status == WS_DISCONNECTING && head.opcode() == WS_DISCONNECT){
|
||||||
_controlQueue.pop_front();
|
_controlQueue.pop_front();
|
||||||
_status = WS_DISCONNECTED;
|
_status = WS_DISCONNECTED;
|
||||||
l.unlock();
|
|
||||||
if (_client) _client->close(true);
|
if (_client) _client->close(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -362,65 +364,64 @@ void AsyncWebSocketClient::_onPoll()
|
|||||||
if (!_client)
|
if (!_client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AsyncWebLockGuard l(_lock);
|
#ifdef ESP32
|
||||||
|
std::unique_lock<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
if (_client->canSend() && (!_controlQueue.empty() || !_messageQueue.empty()))
|
if (_client->canSend() && (!_controlQueue.empty() || !_messageQueue.empty()))
|
||||||
{
|
{
|
||||||
l.unlock();
|
|
||||||
_runQueue();
|
_runQueue();
|
||||||
}
|
}
|
||||||
else if (_keepAlivePeriod > 0 && (millis() - _lastMessageTime) >= _keepAlivePeriod && (_controlQueue.empty() && _messageQueue.empty()))
|
else if (_keepAlivePeriod > 0 && (millis() - _lastMessageTime) >= _keepAlivePeriod && (_controlQueue.empty() && _messageQueue.empty()))
|
||||||
{
|
{
|
||||||
l.unlock();
|
#ifdef ESP32
|
||||||
|
lock.unlock();
|
||||||
|
#endif
|
||||||
ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN);
|
ping((uint8_t *)AWSC_PING_PAYLOAD, AWSC_PING_PAYLOAD_LEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocketClient::_runQueue()
|
void AsyncWebSocketClient::_runQueue()
|
||||||
{
|
{
|
||||||
|
// all calls to this method MUST be protected by a mutex lock!
|
||||||
if (!_client)
|
if (!_client)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AsyncWebLockGuard l(_lock);
|
|
||||||
|
|
||||||
_clearQueue();
|
_clearQueue();
|
||||||
|
|
||||||
if (!_controlQueue.empty() && (_messageQueue.empty() || _messageQueue.front().betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front().len() - 1))
|
if (!_controlQueue.empty() && (_messageQueue.empty() || _messageQueue.front().betweenFrames()) && webSocketSendFrameWindow(_client) > (size_t)(_controlQueue.front().len() - 1))
|
||||||
{
|
{
|
||||||
//l.unlock();
|
|
||||||
_controlQueue.front().send(_client);
|
_controlQueue.front().send(_client);
|
||||||
}
|
}
|
||||||
else if (!_messageQueue.empty() && _messageQueue.front().betweenFrames() && webSocketSendFrameWindow(_client))
|
else if (!_messageQueue.empty() && _messageQueue.front().betweenFrames() && webSocketSendFrameWindow(_client))
|
||||||
{
|
{
|
||||||
//l.unlock();
|
|
||||||
_messageQueue.front().send(_client);
|
_messageQueue.front().send(_client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebSocketClient::queueIsFull() const
|
bool AsyncWebSocketClient::queueIsFull() const
|
||||||
{
|
{
|
||||||
size_t size;
|
#ifdef ESP32
|
||||||
{
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
AsyncWebLockGuard l(_lock);
|
#endif
|
||||||
size = _messageQueue.size();
|
size_t size = _messageQueue.size();;
|
||||||
}
|
|
||||||
return (size >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
|
return (size >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AsyncWebSocketClient::queueLen() const
|
size_t AsyncWebSocketClient::queueLen() const
|
||||||
{
|
{
|
||||||
AsyncWebLockGuard l(_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
return _messageQueue.size() + _controlQueue.size();
|
return _messageQueue.size() + _controlQueue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncWebSocketClient::canSend() const
|
bool AsyncWebSocketClient::canSend() const
|
||||||
{
|
{
|
||||||
size_t size;
|
#ifdef ESP32
|
||||||
{
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
AsyncWebLockGuard l(_lock);
|
#endif
|
||||||
size = _messageQueue.size();
|
return _messageQueue.size() < WS_MAX_QUEUED_MESSAGES;
|
||||||
}
|
|
||||||
return size < WS_MAX_QUEUED_MESSAGES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, size_t len, bool mask)
|
void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, size_t len, bool mask)
|
||||||
@@ -429,7 +430,9 @@ void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, si
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
{
|
{
|
||||||
AsyncWebLockGuard l(_lock);
|
#ifdef ESP32
|
||||||
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
_controlQueue.emplace_back(opcode, data, len, mask);
|
_controlQueue.emplace_back(opcode, data, len, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,20 +442,14 @@ void AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, si
|
|||||||
|
|
||||||
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint8_t opcode, bool mask)
|
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint8_t opcode, bool mask)
|
||||||
{
|
{
|
||||||
if(_status != WS_CONNECTED)
|
if(!_client || buffer->size() == 0 || _status != WS_CONNECTED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_client)
|
#ifdef ESP32
|
||||||
return;
|
std::lock_guard<std::mutex> lock(_lock);
|
||||||
|
#endif
|
||||||
if (buffer->size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
{
|
|
||||||
AsyncWebLockGuard l(_lock);
|
|
||||||
if (_messageQueue.size() >= WS_MAX_QUEUED_MESSAGES)
|
if (_messageQueue.size() >= WS_MAX_QUEUED_MESSAGES)
|
||||||
{
|
{
|
||||||
l.unlock();
|
|
||||||
if(closeWhenFull)
|
if(closeWhenFull)
|
||||||
{
|
{
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@@ -471,11 +468,9 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
_messageQueue.emplace_back(buffer, opcode, mask);
|
_messageQueue.emplace_back(buffer, opcode, mask);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_client && _client->canSend())
|
if (_client && _client->canSend())
|
||||||
_runQueue();
|
_runQueue();
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
|
#include <mutex>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#ifndef WS_MAX_QUEUED_MESSAGES
|
#ifndef WS_MAX_QUEUED_MESSAGES
|
||||||
#define WS_MAX_QUEUED_MESSAGES 32
|
#define WS_MAX_QUEUED_MESSAGES 32
|
||||||
@@ -35,7 +36,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|
||||||
#include "AsyncWebSynchronization.h"
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@@ -136,9 +136,9 @@ class AsyncWebSocketClient {
|
|||||||
AsyncWebSocket *_server;
|
AsyncWebSocket *_server;
|
||||||
uint32_t _clientId;
|
uint32_t _clientId;
|
||||||
AwsClientStatus _status;
|
AwsClientStatus _status;
|
||||||
|
#ifdef ESP32
|
||||||
AsyncWebLock _lock;
|
mutable std::mutex _lock;
|
||||||
|
#endif
|
||||||
std::deque<AsyncWebSocketControl> _controlQueue;
|
std::deque<AsyncWebSocketControl> _controlQueue;
|
||||||
std::deque<AsyncWebSocketMessage> _messageQueue;
|
std::deque<AsyncWebSocketMessage> _messageQueue;
|
||||||
bool closeWhenFull = true;
|
bool closeWhenFull = true;
|
||||||
@@ -260,7 +260,9 @@ class AsyncWebSocket: public AsyncWebHandler {
|
|||||||
AwsEventHandler _eventHandler{nullptr};
|
AwsEventHandler _eventHandler{nullptr};
|
||||||
AwsHandshakeHandler _handshakeHandler;
|
AwsHandshakeHandler _handshakeHandler;
|
||||||
bool _enabled;
|
bool _enabled;
|
||||||
AsyncWebLock _lock;
|
#ifdef ESP32
|
||||||
|
mutable std::mutex _lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AsyncWebSocket(const char* url) : _url(url) ,_cNextId(1), _enabled(true) {}
|
explicit AsyncWebSocket(const char* url) : _url(url) ,_cNextId(1), _enabled(true) {}
|
||||||
|
@@ -1,134 +0,0 @@
|
|||||||
#ifndef ASYNCWEBSYNCHRONIZATION_H_
|
|
||||||
#define ASYNCWEBSYNCHRONIZATION_H_
|
|
||||||
|
|
||||||
// Synchronisation is only available on ESP32, as the ESP8266 isn't using FreeRTOS by default
|
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
|
|
||||||
#ifdef ESP32
|
|
||||||
|
|
||||||
// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
|
|
||||||
// Modified 'AsyncWebLock' to just only use mutex since pxCurrentTCB is not
|
|
||||||
// always available. According to example by Arjan Filius, changed name,
|
|
||||||
// added unimplemented version for ESP8266
|
|
||||||
class AsyncPlainLock
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
SemaphoreHandle_t _lock;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncPlainLock() {
|
|
||||||
_lock = xSemaphoreCreateBinary();
|
|
||||||
// In this fails, the system is likely that much out of memory that
|
|
||||||
// we should abort anyways. If assertions are disabled, nothing is lost..
|
|
||||||
assert(_lock);
|
|
||||||
xSemaphoreGive(_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
~AsyncPlainLock() {
|
|
||||||
vSemaphoreDelete(_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lock() const {
|
|
||||||
xSemaphoreTake(_lock, portMAX_DELAY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock() const {
|
|
||||||
xSemaphoreGive(_lock);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is the ESP32 version of the Sync Lock, using the FreeRTOS Semaphore
|
|
||||||
class AsyncWebLock
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
SemaphoreHandle_t _lock;
|
|
||||||
mutable TaskHandle_t _lockedBy{};
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsyncWebLock()
|
|
||||||
{
|
|
||||||
_lock = xSemaphoreCreateBinary();
|
|
||||||
// In this fails, the system is likely that much out of memory that
|
|
||||||
// we should abort anyways. If assertions are disabled, nothing is lost..
|
|
||||||
assert(_lock);
|
|
||||||
_lockedBy = NULL;
|
|
||||||
xSemaphoreGive(_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
~AsyncWebLock() {
|
|
||||||
vSemaphoreDelete(_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lock() const {
|
|
||||||
const auto currentTask = xTaskGetCurrentTaskHandle();
|
|
||||||
if (_lockedBy != currentTask) {
|
|
||||||
xSemaphoreTake(_lock, portMAX_DELAY);
|
|
||||||
_lockedBy = currentTask;
|
|
||||||
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 {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Same for AsyncPlainLock, for ESP8266 this is just the unimplemented version above.
|
|
||||||
using AsyncPlainLock = AsyncWebLock;
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock() {
|
|
||||||
if (_lock) {
|
|
||||||
_lock->unlock();
|
|
||||||
_lock = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ASYNCWEBSYNCHRONIZATION_H_
|
|
Reference in New Issue
Block a user