#pragma once #ifdef NETWORK #include "WebSocketClientBase.h" #include #include #include #include #include #include #include namespace ZL { // Lock-free SPSC double-buffer: producer pushes to one buffer, consumer swaps and drains the other. // No mutexes; avoids contention under high message load. class WebSocketClient : public WebSocketClientBase { private: boost::asio::io_context& ioc_; std::unique_ptr> ws_; boost::beast::flat_buffer buffer_; // Incoming messages: I/O thread pushes, main thread drains in Poll() using MessageBuf = std::vector; MessageBuf readBuffer0_; MessageBuf readBuffer1_; std::atomic readProducerBuf_; std::atomic readConsumerBuf_; // Outgoing messages: main thread pushes in Send(), doWrite()/completion drains using WriteBuf = std::vector>; WriteBuf writeBuffer0_; WriteBuf writeBuffer1_; std::atomic writeProducerBuf_; std::atomic writeConsumerBuf_; WriteBuf* currentWriteBuf_ = nullptr; size_t currentWriteIndex_ = 0; std::atomic isWriting_{ false }; bool connected = false; void startAsyncRead(); void processIncomingMessage(const std::string& msg); public: explicit WebSocketClient(boost::asio::io_context& ioc) : ioc_(ioc) , readProducerBuf_(&readBuffer0_) , readConsumerBuf_(&readBuffer1_) , writeProducerBuf_(&writeBuffer0_) , writeConsumerBuf_(&writeBuffer1_) {} void Connect(const std::string& host, uint16_t port) override; void Disconnect() override; void Poll() override; void Send(const std::string& message) override; void doWrite(); bool IsConnected() const override { return connected; } }; } #endif