1
0

cNetwork: Added multithreading protection.

This commit is contained in:
Mattes D 2015-01-12 15:45:30 +01:00
parent d8ac99a037
commit ddb1818dd5
3 changed files with 35 additions and 4 deletions

View File

@ -1,5 +1,6 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "CriticalSection.h"

View File

@ -12,6 +12,7 @@
#include <event2/listener.h> #include <event2/listener.h>
#include <thread> #include <thread>
#include "Event.h" #include "Event.h"
#include "CriticalSection.h"
@ -197,6 +198,9 @@ protected:
/** Container for all currently active connections on this server. */ /** Container for all currently active connections on this server. */
cTCPLinkImplPtrs m_Connections; cTCPLinkImplPtrs m_Connections;
/** Mutex protecting m_Connections againt multithreaded access. */
cCriticalSection m_CS;
/** The callback called by LibEvent upon incoming connection. */ /** The callback called by LibEvent upon incoming connection. */
static void Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self); static void Callback(evconnlistener * a_Listener, evutil_socket_t a_Socket, sockaddr * a_Addr, int a_Len, void * a_Self);
@ -289,6 +293,9 @@ protected:
/** Container for all pending IP lookups. */ /** Container for all pending IP lookups. */
cIPLookupPtrs m_IPLookups; cIPLookupPtrs m_IPLookups;
/** Mutex protecting all containers against multithreaded access. */
cCriticalSection m_CS;
/** Initializes the LibEvent internals. */ /** Initializes the LibEvent internals. */
cNetworkSingleton(void); cNetworkSingleton(void);
@ -587,6 +594,7 @@ void cTCPLinkImpl::Shutdown(void)
void cTCPLinkImpl::Close(void) void cTCPLinkImpl::Close(void)
{ {
// Disable all events on the socket, but keep it alive (multithreading):
bufferevent_disable(m_BufferEvent, EV_READ | EV_WRITE); bufferevent_disable(m_BufferEvent, EV_READ | EV_WRITE);
if (m_Server == nullptr) if (m_Server == nullptr)
{ {
@ -790,7 +798,10 @@ void cServerHandleImpl::Close(void)
// Shutdown all connections: // Shutdown all connections:
cTCPLinkImplPtrs Conns; cTCPLinkImplPtrs Conns;
std::swap(Conns, m_Connections); {
cCSLock Lock(m_CS);
std::swap(Conns, m_Connections);
}
for (auto conn: Conns) for (auto conn: Conns)
{ {
conn->Shutdown(); conn->Shutdown();
@ -902,7 +913,10 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_
// Create a new cTCPLink for the incoming connection: // Create a new cTCPLink for the incoming connection:
cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, Self->m_LinkCallbacks, Self, a_Addr, a_Len); cTCPLinkImplPtr Link = std::make_shared<cTCPLinkImpl>(a_Socket, Self->m_LinkCallbacks, Self, a_Addr, a_Len);
Self->m_Connections.push_back(Link); {
cCSLock Lock(Self->m_CS);
Self->m_Connections.push_back(Link);
} // Lock(m_CS)
// Call the OnAccepted callback: // Call the OnAccepted callback:
Self->m_ListenCallbacks->OnAccepted(*Link); Self->m_ListenCallbacks->OnAccepted(*Link);
@ -914,6 +928,7 @@ void cServerHandleImpl::Callback(evconnlistener * a_Listener, evutil_socket_t a_
void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link) void cServerHandleImpl::RemoveLink(const cTCPLinkImpl * a_Link)
{ {
cCSLock Lock(m_CS);
for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr)
{ {
if (itr->get() == a_Link) if (itr->get() == a_Link)
@ -1060,7 +1075,10 @@ bool cNetworkSingleton::Connect(
{ {
// Add a connection request to the queue: // Add a connection request to the queue:
cTCPLinkImplPtr ConnRequest = std::make_shared<cTCPLinkImpl>(a_LinkCallbacks); cTCPLinkImplPtr ConnRequest = std::make_shared<cTCPLinkImpl>(a_LinkCallbacks);
m_Connections.push_back(ConnRequest); {
cCSLock Lock(m_CS);
m_Connections.push_back(ConnRequest);
} // Lock(m_CS)
// Queue the connection: // Queue the connection:
if (!ConnRequest->Connect(a_Host, a_Port, a_ConnectCallbacks)) if (!ConnRequest->Connect(a_Host, a_Port, a_ConnectCallbacks))
@ -1088,6 +1106,7 @@ cServerHandlePtr cNetworkSingleton::Listen(
{ {
return res; return res;
} }
cCSLock Lock(m_CS);
m_Servers.push_back(res); m_Servers.push_back(res);
return res; return res;
} }
@ -1103,6 +1122,7 @@ bool cNetworkSingleton::HostnameToIP(
{ {
try try
{ {
cCSLock Lock(m_CS);
m_HostnameLookups.push_back(std::make_shared<cHostnameLookup>(a_Hostname, a_Callbacks)); m_HostnameLookups.push_back(std::make_shared<cHostnameLookup>(a_Hostname, a_Callbacks));
} }
catch (...) catch (...)
@ -1122,6 +1142,7 @@ bool cNetworkSingleton::IPToHostName(
{ {
try try
{ {
cCSLock Lock(m_CS);
m_IPLookups.push_back(std::make_shared<cIPLookup>(a_IP, a_Callbacks)); m_IPLookups.push_back(std::make_shared<cIPLookup>(a_IP, a_Callbacks));
} }
catch (...) catch (...)
@ -1165,6 +1186,7 @@ void cNetworkSingleton::RunEventLoop(cNetworkSingleton * a_Self)
void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup) void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameLookup)
{ {
cCSLock Lock(m_CS);
for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr) for (auto itr = m_HostnameLookups.begin(), end = m_HostnameLookups.end(); itr != end; ++itr)
{ {
if (itr->get() == a_HostnameLookup) if (itr->get() == a_HostnameLookup)
@ -1181,6 +1203,7 @@ void cNetworkSingleton::RemoveHostnameLookup(const cHostnameLookup * a_HostnameL
void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup) void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup)
{ {
cCSLock Lock(m_CS);
for (auto itr = m_IPLookups.begin(), end = m_IPLookups.end(); itr != end; ++itr) for (auto itr = m_IPLookups.begin(), end = m_IPLookups.end(); itr != end; ++itr)
{ {
if (itr->get() == a_IPLookup) if (itr->get() == a_IPLookup)
@ -1197,6 +1220,7 @@ void cNetworkSingleton::RemoveIPLookup(const cIPLookup * a_IPLookup)
void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link) void cNetworkSingleton::RemoveLink(const cTCPLinkImpl * a_Link)
{ {
cCSLock Lock(m_CS);
for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr) for (auto itr = m_Connections.begin(), end = m_Connections.end(); itr != end; ++itr)
{ {
if (itr->get() == a_Link) if (itr->get() == a_Link)

View File

@ -6,7 +6,13 @@ include_directories(${CMAKE_SOURCE_DIR}/src/)
include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include) include_directories(${CMAKE_SOURCE_DIR}/lib/libevent/include)
add_definitions(-DTEST_GLOBALS=1) add_definitions(-DTEST_GLOBALS=1)
add_library(Network ${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp ${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp ${CMAKE_SOURCE_DIR}/src/StringUtils.cpp) add_library(Network
${CMAKE_SOURCE_DIR}/src/OSSupport/Network.cpp
${CMAKE_SOURCE_DIR}/src/OSSupport/CriticalSection.cpp
${CMAKE_SOURCE_DIR}/src/OSSupport/Event.cpp
${CMAKE_SOURCE_DIR}/src/StringUtils.cpp
)
target_link_libraries(Network event_core event_extra) target_link_libraries(Network event_core event_extra)
if (MSVC) if (MSVC)
target_link_libraries(Network ws2_32.lib) target_link_libraries(Network ws2_32.lib)