lib/net: Use standard mutex primitives in TCP socket code

This commit is contained in:
Povilas Kanapickas 2021-11-03 02:58:30 +02:00
parent cbf22ad589
commit 836a65cda4
5 changed files with 29 additions and 41 deletions

View File

@ -21,7 +21,6 @@
#include "net/TSocketMultiplexerMethodJob.h" #include "net/TSocketMultiplexerMethodJob.h"
#include "base/TMethodEventJob.h" #include "base/TMethodEventJob.h"
#include "net/TCPSocket.h" #include "net/TCPSocket.h"
#include "mt/Lock.h"
#include "arch/XArch.h" #include "arch/XArch.h"
#include "base/Log.h" #include "base/Log.h"
#include "base/String.h" #include "base/String.h"
@ -749,7 +748,7 @@ MultiplexerJobStatus SecureSocket::serviceConnect(ISocketMultiplexerJob* job,
{ {
(void) read; (void) read;
Lock lock(&getMutex()); std::lock_guard<std::mutex> lock(tcp_mutex_);
int status = 0; int status = 0;
#ifdef SYSAPI_WIN32 #ifdef SYSAPI_WIN32
@ -782,7 +781,7 @@ MultiplexerJobStatus SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
bool read, bool write, bool error) bool read, bool write, bool error)
{ {
(void) read; (void) read;
Lock lock(&getMutex()); std::lock_guard<std::mutex> lock(tcp_mutex_);
int status = 0; int status = 0;
#ifdef SYSAPI_WIN32 #ifdef SYSAPI_WIN32

View File

@ -24,8 +24,6 @@
#include "net/TSocketMultiplexerMethodJob.h" #include "net/TSocketMultiplexerMethodJob.h"
#include "net/XSocket.h" #include "net/XSocket.h"
#include "io/XIO.h" #include "io/XIO.h"
#include "mt/Lock.h"
#include "mt/Mutex.h"
#include "arch/Arch.h" #include "arch/Arch.h"
#include "arch/XArch.h" #include "arch/XArch.h"
#include "base/IEventQueue.h" #include "base/IEventQueue.h"
@ -38,7 +36,6 @@ TCPListenSocket::TCPListenSocket(IEventQueue* events, SocketMultiplexer* socketM
m_events(events), m_events(events),
m_socketMultiplexer(socketMultiplexer) m_socketMultiplexer(socketMultiplexer)
{ {
m_mutex = new Mutex;
try { try {
m_socket = ARCH->newSocket(family, IArchNetwork::kSTREAM); m_socket = ARCH->newSocket(family, IArchNetwork::kSTREAM);
} }
@ -58,14 +55,13 @@ TCPListenSocket::~TCPListenSocket()
catch (...) { catch (...) {
// ignore // ignore
} }
delete m_mutex;
} }
void void
TCPListenSocket::bind(const NetworkAddress& addr) TCPListenSocket::bind(const NetworkAddress& addr)
{ {
try { try {
Lock lock(m_mutex); std::lock_guard<std::mutex> lock(mutex_);
ARCH->setReuseAddrOnSocket(m_socket, true); ARCH->setReuseAddrOnSocket(m_socket, true);
ARCH->bindSocket(m_socket, addr.getAddress()); ARCH->bindSocket(m_socket, addr.getAddress());
ARCH->listenOnSocket(m_socket); ARCH->listenOnSocket(m_socket);
@ -88,7 +84,7 @@ TCPListenSocket::bind(const NetworkAddress& addr)
void void
TCPListenSocket::close() TCPListenSocket::close()
{ {
Lock lock(m_mutex); std::lock_guard<std::mutex> lock(mutex_);
if (m_socket == NULL) { if (m_socket == NULL) {
throw XIOClosed(); throw XIOClosed();
} }

View File

@ -22,7 +22,8 @@
#include "net/ISocketMultiplexerJob.h" #include "net/ISocketMultiplexerJob.h"
#include "arch/IArchNetwork.h" #include "arch/IArchNetwork.h"
class Mutex; #include <mutex>
class IEventQueue; class IEventQueue;
class SocketMultiplexer; class SocketMultiplexer;
@ -52,7 +53,7 @@ public:
protected: protected:
ArchSocket m_socket; ArchSocket m_socket;
Mutex* m_mutex; std::mutex mutex_;
IEventQueue* m_events; IEventQueue* m_events;
SocketMultiplexer* m_socketMultiplexer; SocketMultiplexer* m_socketMultiplexer;
}; };

View File

@ -22,7 +22,6 @@
#include "net/SocketMultiplexer.h" #include "net/SocketMultiplexer.h"
#include "net/TSocketMultiplexerMethodJob.h" #include "net/TSocketMultiplexerMethodJob.h"
#include "net/XSocket.h" #include "net/XSocket.h"
#include "mt/Lock.h"
#include "arch/Arch.h" #include "arch/Arch.h"
#include "arch/XArch.h" #include "arch/XArch.h"
#include "base/Log.h" #include "base/Log.h"
@ -38,8 +37,6 @@ static const std::size_t MAX_INPUT_BUFFER_SIZE = 1024 * 1024;
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, IArchNetwork::EAddressFamily family) : TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, IArchNetwork::EAddressFamily family) :
IDataSocket(events), IDataSocket(events),
m_events(events), m_events(events),
m_mutex(),
m_flushed(&m_mutex, true),
m_socketMultiplexer(socketMultiplexer) m_socketMultiplexer(socketMultiplexer)
{ {
try { try {
@ -57,9 +54,7 @@ TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer,
TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) : TCPSocket::TCPSocket(IEventQueue* events, SocketMultiplexer* socketMultiplexer, ArchSocket socket) :
IDataSocket(events), IDataSocket(events),
m_events(events), m_events(events),
m_mutex(),
m_socket(socket), m_socket(socket),
m_flushed(&m_mutex, true),
m_socketMultiplexer(socketMultiplexer) m_socketMultiplexer(socketMultiplexer)
{ {
assert(m_socket != NULL); assert(m_socket != NULL);
@ -104,7 +99,7 @@ TCPSocket::close()
// remove ourself from the multiplexer // remove ourself from the multiplexer
setJob(NULL); setJob(NULL);
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// clear buffers and enter disconnected state // clear buffers and enter disconnected state
if (m_connected) { if (m_connected) {
@ -136,7 +131,7 @@ UInt32
TCPSocket::read(void* buffer, UInt32 n) TCPSocket::read(void* buffer, UInt32 n)
{ {
// copy data directly from our input buffer // copy data directly from our input buffer
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
UInt32 size = m_inputBuffer.getSize(); UInt32 size = m_inputBuffer.getSize();
if (n > size) { if (n > size) {
n = size; n = size;
@ -160,7 +155,7 @@ TCPSocket::write(const void* buffer, UInt32 n)
{ {
bool wasEmpty; bool wasEmpty;
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// must not have shutdown output // must not have shutdown output
if (!m_writable) { if (!m_writable) {
@ -178,7 +173,7 @@ TCPSocket::write(const void* buffer, UInt32 n)
m_outputBuffer.write(buffer, n); m_outputBuffer.write(buffer, n);
// there's data to write // there's data to write
m_flushed = false; is_flushed_ = false;
} }
// make sure we're waiting to write // make sure we're waiting to write
@ -190,10 +185,8 @@ TCPSocket::write(const void* buffer, UInt32 n)
void void
TCPSocket::flush() TCPSocket::flush()
{ {
Lock lock(&m_mutex); std::unique_lock<std::mutex> lock(tcp_mutex_);
while (m_flushed == false) { flushed_cv_.wait(lock, [this](){ return is_flushed_; });
m_flushed.wait();
}
} }
void void
@ -201,7 +194,7 @@ TCPSocket::shutdownInput()
{ {
bool useNewJob = false; bool useNewJob = false;
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// shutdown socket for reading // shutdown socket for reading
try { try {
@ -228,7 +221,7 @@ TCPSocket::shutdownOutput()
{ {
bool useNewJob = false; bool useNewJob = false;
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// shutdown socket for writing // shutdown socket for writing
try { try {
@ -253,7 +246,7 @@ TCPSocket::shutdownOutput()
bool bool
TCPSocket::isReady() const TCPSocket::isReady() const
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
return (m_inputBuffer.getSize() > 0); return (m_inputBuffer.getSize() > 0);
} }
@ -268,7 +261,7 @@ TCPSocket::isFatal() const
UInt32 UInt32
TCPSocket::getSize() const TCPSocket::getSize() const
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
return m_inputBuffer.getSize(); return m_inputBuffer.getSize();
} }
@ -276,7 +269,7 @@ void
TCPSocket::connect(const NetworkAddress& addr) TCPSocket::connect(const NetworkAddress& addr)
{ {
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// fail on attempts to reconnect // fail on attempts to reconnect
if (m_socket == NULL || m_connected) { if (m_socket == NULL || m_connected) {
@ -463,8 +456,8 @@ TCPSocket::discardWrittenData(int bytesWrote)
m_outputBuffer.pop(bytesWrote); m_outputBuffer.pop(bytesWrote);
if (m_outputBuffer.getSize() == 0) { if (m_outputBuffer.getSize() == 0) {
sendEvent(m_events->forIStream().outputFlushed()); sendEvent(m_events->forIStream().outputFlushed());
m_flushed = true; is_flushed_ = true;
m_flushed.broadcast(); flushed_cv_.notify_all();
} }
} }
@ -490,8 +483,8 @@ TCPSocket::onOutputShutdown()
m_writable = false; m_writable = false;
// we're now flushed // we're now flushed
m_flushed = true; is_flushed_ = true;
m_flushed.broadcast(); flushed_cv_.notify_all();
} }
void void
@ -505,7 +498,7 @@ TCPSocket::onDisconnected()
MultiplexerJobStatus TCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bool, bool write, bool error) MultiplexerJobStatus TCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bool, bool write, bool error)
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
// should only check for errors if error is true but checking a new // should only check for errors if error is true but checking a new
// socket (and a socket that's connecting should be new) for errors // socket (and a socket that's connecting should be new) for errors
@ -548,7 +541,7 @@ MultiplexerJobStatus TCPSocket::serviceConnecting(ISocketMultiplexerJob* job, bo
MultiplexerJobStatus TCPSocket::serviceConnected(ISocketMultiplexerJob* job, MultiplexerJobStatus TCPSocket::serviceConnected(ISocketMultiplexerJob* job,
bool read, bool write, bool error) bool read, bool write, bool error)
{ {
Lock lock(&m_mutex); std::lock_guard<std::mutex> lock(tcp_mutex_);
if (error) { if (error) {
sendEvent(m_events->forISocket().disconnected()); sendEvent(m_events->forISocket().disconnected());

View File

@ -22,11 +22,11 @@
#include "net/ISocketMultiplexerJob.h" #include "net/ISocketMultiplexerJob.h"
#include "io/StreamBuffer.h" #include "io/StreamBuffer.h"
#include "mt/CondVar.h" #include "mt/CondVar.h"
#include "mt/Mutex.h"
#include "arch/IArchNetwork.h" #include "arch/IArchNetwork.h"
#include <condition_variable>
#include <memory> #include <memory>
#include <mutex>
class Mutex;
class Thread; class Thread;
class IEventQueue; class IEventQueue;
class SocketMultiplexer; class SocketMultiplexer;
@ -81,8 +81,6 @@ protected:
bool isReadable() { return m_readable; } bool isReadable() { return m_readable; }
bool isWritable() { return m_writable; } bool isWritable() { return m_writable; }
Mutex& getMutex() { return m_mutex; }
void sendEvent(Event::Type); void sendEvent(Event::Type);
void discardWrittenData(int bytesWrote); void discardWrittenData(int bytesWrote);
@ -106,9 +104,10 @@ protected:
StreamBuffer m_inputBuffer; StreamBuffer m_inputBuffer;
StreamBuffer m_outputBuffer; StreamBuffer m_outputBuffer;
mutable std::mutex tcp_mutex_;
private: private:
Mutex m_mutex;
ArchSocket m_socket; ArchSocket m_socket;
CondVar<bool> m_flushed; std::condition_variable flushed_cv_;
bool is_flushed_ = true;
SocketMultiplexer* m_socketMultiplexer; SocketMultiplexer* m_socketMultiplexer;
}; };