From 261095fa12e4302b7937075ce43f1fd311902046 Mon Sep 17 00:00:00 2001 From: Benjamin Sergeant Date: Sat, 15 Aug 2020 15:28:15 -0700 Subject: [PATCH] (socket server) do not create a select interrupt object everytime when polling for notifications while waiting for new connections, instead use a persistent one which is a member variable --- docs/CHANGELOG.md | 4 ++++ ixwebsocket/IXSelectInterrupt.cpp | 3 +++ ixwebsocket/IXSelectInterrupt.h | 7 +++++++ ixwebsocket/IXSocket.cpp | 6 ++---- ixwebsocket/IXSocket.h | 9 +-------- ixwebsocket/IXSocketServer.cpp | 9 ++++++--- ixwebsocket/IXSocketServer.h | 4 ++++ ixwebsocket/IXWebSocketTransport.cpp | 6 +++--- ixwebsocket/IXWebSocketVersion.h | 2 +- 9 files changed, 31 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 92ec03e6..1df1d94b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,10 @@ All changes to this project will be documented in this file. +## [10.2.1] - 2020-08-15 + +(socket server) do not create a select interrupt object everytime when polling for notifications while waiting for new connections, instead use a persistent one which is a member variable + ## [10.2.0] - 2020-08-14 (ixwebsocket client) handle HTTP redirects diff --git a/ixwebsocket/IXSelectInterrupt.cpp b/ixwebsocket/IXSelectInterrupt.cpp index 3c7afd8a..36dc66c9 100644 --- a/ixwebsocket/IXSelectInterrupt.cpp +++ b/ixwebsocket/IXSelectInterrupt.cpp @@ -8,6 +8,9 @@ namespace ix { + const uint64_t SelectInterrupt::kSendRequest = 1; + const uint64_t SelectInterrupt::kCloseRequest = 2; + SelectInterrupt::SelectInterrupt() { ; diff --git a/ixwebsocket/IXSelectInterrupt.h b/ixwebsocket/IXSelectInterrupt.h index 6d03f32d..c3bb7f3f 100644 --- a/ixwebsocket/IXSelectInterrupt.h +++ b/ixwebsocket/IXSelectInterrupt.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include @@ -23,5 +24,11 @@ namespace ix virtual bool clear(); virtual uint64_t read(); virtual int getFd() const; + + // Used as special codes for pipe communication + static const uint64_t kSendRequest; + static const uint64_t kCloseRequest; }; + + using SelectInterruptPtr = std::unique_ptr; } // namespace ix diff --git a/ixwebsocket/IXSocket.cpp b/ixwebsocket/IXSocket.cpp index 9ef78bb7..46fc1018 100644 --- a/ixwebsocket/IXSocket.cpp +++ b/ixwebsocket/IXSocket.cpp @@ -27,8 +27,6 @@ namespace ix { const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout; - const uint64_t Socket::kSendRequest = 1; - const uint64_t Socket::kCloseRequest = 2; constexpr size_t Socket::kChunkSize; Socket::Socket(int fd) @@ -96,11 +94,11 @@ namespace ix { uint64_t value = selectInterrupt->read(); - if (value == kSendRequest) + if (value == SelectInterrupt::kSendRequest) { pollResult = PollResultType::SendRequest; } - else if (value == kCloseRequest) + else if (value == SelectInterrupt::kCloseRequest) { pollResult = PollResultType::CloseRequest; } diff --git a/ixwebsocket/IXSocket.h b/ixwebsocket/IXSocket.h index 84b0b737..e27e2752 100644 --- a/ixwebsocket/IXSocket.h +++ b/ixwebsocket/IXSocket.h @@ -34,12 +34,10 @@ typedef SSIZE_T ssize_t; #include "IXCancellationRequest.h" #include "IXProgressCallback.h" +#include "IXSelectInterrupt.h" namespace ix { - class SelectInterrupt; - using SelectInterruptPtr = std::unique_ptr; - enum class PollResultType { ReadyForRead = 0, @@ -96,11 +94,6 @@ namespace ix int sockfd, const SelectInterruptPtr& selectInterrupt); - - // Used as special codes for pipe communication - static const uint64_t kSendRequest; - static const uint64_t kCloseRequest; - protected: std::atomic _sockfd; std::mutex _socketMutex; diff --git a/ixwebsocket/IXSocketServer.cpp b/ixwebsocket/IXSocketServer.cpp index 6c33420b..8ae0bed7 100644 --- a/ixwebsocket/IXSocketServer.cpp +++ b/ixwebsocket/IXSocketServer.cpp @@ -12,6 +12,7 @@ #include "IXSocket.h" #include "IXSocketConnect.h" #include "IXSocketFactory.h" +#include "IXSelectInterruptFactory.h" #include #include #include @@ -36,6 +37,7 @@ namespace ix , _stop(false) , _stopGc(false) , _connectionStateFactory(&ConnectionState::createConnectionState) + , _acceptSelectInterrupt(createSelectInterrupt()) { } @@ -193,6 +195,7 @@ namespace ix if (_thread.joinable()) { _stop = true; + _acceptSelectInterrupt->notify(SelectInterrupt::kCloseRequest); // Wake up select _thread.join(); _stop = false; } @@ -249,7 +252,7 @@ namespace ix // Set the socket to non blocking mode, so that accept calls are not blocking SocketConnect::configure(_serverFd); - setThreadName("SocketServer::listen"); + setThreadName("SocketServer::accept"); for (;;) { @@ -258,9 +261,8 @@ namespace ix // Use poll to check whether a new connection is in progress int timeoutMs = 10; bool readyToRead = true; - auto selectInterrupt = std::make_unique(); PollResultType pollResult = - Socket::poll(readyToRead, timeoutMs, _serverFd, selectInterrupt); + Socket::poll(readyToRead, timeoutMs, _serverFd, _acceptSelectInterrupt); if (pollResult == PollResultType::Error) { @@ -308,6 +310,7 @@ namespace ix continue; } + // Retrieve connection info, the ip address of the remote peer/client) std::unique_ptr connectionInfo; if (_addressFamily == AF_INET) diff --git a/ixwebsocket/IXSocketServer.h b/ixwebsocket/IXSocketServer.h index ff7a36b7..feac52e1 100644 --- a/ixwebsocket/IXSocketServer.h +++ b/ixwebsocket/IXSocketServer.h @@ -8,6 +8,7 @@ #include "IXConnectionInfo.h" #include "IXConnectionState.h" +#include "IXSelectInterrupt.h" #include "IXSocketTLSOptions.h" #include #include @@ -112,5 +113,8 @@ namespace ix size_t getConnectionsThreadsCount(); SocketTLSOptions _socketTLSOptions; + + // to wake up from select + SelectInterruptPtr _acceptSelectInterrupt; }; } // namespace ix diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index 43e9c53b..186c064f 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -659,7 +659,7 @@ namespace ix // send back the CLOSE frame sendCloseFrame(code, reason); - wakeUpFromPoll(Socket::kCloseRequest); + wakeUpFromPoll(SelectInterrupt::kCloseRequest); bool remote = true; closeSocketAndSwitchToClosedState(code, reason, _rxbuf.size(), remote); @@ -879,7 +879,7 @@ namespace ix // Request to flush the send buffer on the background thread if it isn't empty if (!isSendBufferEmpty()) { - wakeUpFromPoll(Socket::kSendRequest); + wakeUpFromPoll(SelectInterrupt::kSendRequest); // FIXME: we should have a timeout when sending large messages: see #131 if (_blockingSend && !flushSendBuffer()) @@ -1148,7 +1148,7 @@ namespace ix sendCloseFrame(code, reason); // wake up the poll, but do not close yet - wakeUpFromPoll(Socket::kSendRequest); + wakeUpFromPoll(SelectInterrupt::kSendRequest); } size_t WebSocketTransport::bufferedAmount() const diff --git a/ixwebsocket/IXWebSocketVersion.h b/ixwebsocket/IXWebSocketVersion.h index 8ffbff54..1560aeb6 100644 --- a/ixwebsocket/IXWebSocketVersion.h +++ b/ixwebsocket/IXWebSocketVersion.h @@ -6,4 +6,4 @@ #pragma once -#define IX_WEBSOCKET_VERSION "10.2.1" +#define IX_WEBSOCKET_VERSION "10.2.2"