lib/net: Use standard mutex primitives in TCP socket code
This commit is contained in:
parent
cbf22ad589
commit
836a65cda4
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue