Only run enet command in listening thread

And use sleep instead of timeout for new code
This commit is contained in:
Benau 2018-03-10 14:56:32 +08:00
parent c50cdd9d68
commit 4dea283965
6 changed files with 57 additions and 24 deletions

View File

@ -174,7 +174,6 @@ void Network::broadcastPacket(NetworkString *data, bool reliable)
ENetPacket* packet = enet_packet_create(data->getData(), data->size() + 1,
reliable ? ENET_PACKET_FLAG_RELIABLE
: ENET_PACKET_FLAG_UNSEQUENCED);
auto lock = acquireEnetLock();
enet_host_broadcast(m_host, 0, packet);
} // broadcastPacket

View File

@ -31,7 +31,6 @@
#define WIN32_LEAN_AND_MEAN
#include <enet/enet.h>
#include <mutex>
#include <stdio.h>
class BareNetworkString;
@ -48,8 +47,6 @@ private:
/** ENet host interfacing sockets. */
ENetHost* m_host;
std::mutex m_enet_mutex;
/** Where to log packets. If NULL for FILE* logging is disabled. */
static Synchronised<FILE*> m_log_file;
@ -72,9 +69,6 @@ public:
void broadcastPacket(NetworkString *data,
bool reliable = true);
// ------------------------------------------------------------------------
std::unique_lock<std::mutex> acquireEnetLock()
{ return std::unique_lock<std::mutex>(m_enet_mutex); }
// ------------------------------------------------------------------------
/** Returns a pointer to the ENet host object. */
ENetHost* getENetHost() { return m_host; }
}; // class Network

View File

@ -62,6 +62,7 @@
#include <limits>
#include <random>
#include <string>
#include <utility>
STKHost *STKHost::m_stk_host = NULL;
bool STKHost::m_enable_console = false;
@ -750,7 +751,26 @@ void STKHost::mainLoop()
handleDirectSocketRequest(direct_socket);
} // if discovery host
while (enet_host_service(host, &event, 20) != 0)
std::list<std::tuple<ENetPeer*, ENetPacket*, uint32_t,
ENetCommandType> > copied_list;
std::unique_lock<std::mutex> lock(m_enet_cmd_mutex);
std::swap(copied_list, m_enet_cmd);
lock.unlock();
for (auto& p : copied_list)
{
switch (std::get<3>(p))
{
case ECT_SEND_PACKET:
enet_peer_send(std::get<0>(p), (uint8_t)std::get<2>(p),
std::get<1>(p));
break;
case ECT_DISCONNECT:
enet_peer_disconnect(std::get<0>(p), std::get<2>(p));
break;
}
}
while (enet_host_service(host, &event, 0) != 0)
{
if (event.type == ENET_EVENT_TYPE_NONE)
continue;
@ -759,7 +779,7 @@ void STKHost::mainLoop()
if (event.type == ENET_EVENT_TYPE_CONNECT)
{
auto stk_peer =
std::make_shared<STKPeer>(event.peer, m_network);
std::make_shared<STKPeer>(event.peer, this);
std::unique_lock<std::mutex> lock(m_peers_mutex);
m_peers[event.peer] = stk_peer;
lock.unlock();
@ -822,7 +842,8 @@ void STKHost::mainLoop()
else
delete stk_event;
} // while enet_host_service
} // while m_exit_flag.test_and_set()
StkTime::sleep(10);
} // while m_exit_timeout.load() > StkTime::getRealTime()
delete direct_socket;
Log::info("STKHost", "Listening has been stopped.");
} // mainLoop

View File

@ -25,7 +25,6 @@
#include "network/network.hpp"
#include "network/network_string.hpp"
#include "network/transport_address.hpp"
#include "utils/synchronised.hpp"
#include "irrString.h"
@ -36,16 +35,24 @@
#include <enet/enet.h>
#include <atomic>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <thread>
#include <tuple>
class GameSetup;
class NetworkPlayerProfile;
class Server;
class SeparateProcess;
enum ENetCommandType : unsigned int
{
ECT_SEND_PACKET = 0,
ECT_DISCONNECT = 1
};
class STKHost
{
public:
@ -75,6 +82,15 @@ private:
/** Make sure the removing or adding a peer is thread-safe. */
std::mutex m_peers_mutex;
/** Let (atm enet_peer_send and enet_peer_disconnect) run in the listening
* thread. */
std::list<std::tuple<ENetPeer*/*peer receive*/,
ENetPacket*/*packet to send*/, uint32_t/*integer data*/,
ENetCommandType> > m_enet_cmd;
/** Protect \ref m_enet_cmd from multiple threads usage. */
std::mutex m_enet_cmd_mutex;
/** The list of peers connected to this instance. */
std::map<ENetPeer*, std::shared_ptr<STKPeer> > m_peers;
@ -198,7 +214,13 @@ public:
std::vector<NetworkPlayerProfile*> getMyPlayerProfiles();
void setErrorMessage(const irr::core::stringw &message);
bool isAuthorisedToControl() const;
//-------------------------------------------------------------------------
void addEnetCommand(ENetPeer* peer, ENetPacket* packet, uint32_t i,
ENetCommandType ect)
{
std::lock_guard<std::mutex> lock(m_enet_cmd_mutex);
m_enet_cmd.emplace_back(peer, packet, i, ect);
}
// ------------------------------------------------------------------------
/** Returns the last error (or "" if no error has happened). */
const irr::core::stringw& getErrorMessage() const

View File

@ -29,8 +29,8 @@
/** Constructor for an empty peer.
*/
STKPeer::STKPeer(ENetPeer *enet_peer, Network* network)
: m_peer_address(enet_peer->address), m_network(network)
STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host)
: m_peer_address(enet_peer->address), m_host(host)
{
m_enet_peer = enet_peer;
m_is_authorised = false;
@ -48,8 +48,7 @@ STKPeer::~STKPeer()
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
a != m_peer_address)
return;
auto lock = m_network->acquireEnetLock();
enet_peer_disconnect(m_enet_peer, PDI_NORMAL);
m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT);
} // ~STKPeer
//-----------------------------------------------------------------------------
@ -61,8 +60,7 @@ void STKPeer::kick()
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
a != m_peer_address)
return;
auto lock = m_network->acquireEnetLock();
enet_peer_disconnect(m_enet_peer, PDI_KICK);
m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT);
} // kick
//-----------------------------------------------------------------------------
@ -86,8 +84,7 @@ void STKPeer::sendPacket(NetworkString *data, bool reliable)
data->getTotalSize(),
(reliable ? ENET_PACKET_FLAG_RELIABLE
: ENET_PACKET_FLAG_UNSEQUENCED));
auto lock = m_network->acquireEnetLock();
enet_peer_send(m_enet_peer, 0, packet);
m_host->addEnetCommand(m_enet_peer, packet, 0, ECT_SEND_PACKET);
} // sendPacket
//-----------------------------------------------------------------------------
@ -122,6 +119,6 @@ bool STKPeer::isSamePeer(const ENetPeer* peer) const
*/
std::vector<NetworkPlayerProfile*> STKPeer::getAllPlayerProfiles()
{
return STKHost::get()->getGameSetup()->getAllPlayersOnHost(getHostId());
return m_host->getGameSetup()->getAllPlayersOnHost(getHostId());
} // getAllPlayerProfiles

View File

@ -31,9 +31,9 @@
#include <vector>
class Network;
class NetworkPlayerProfile;
class NetworkString;
class STKHost;
class TransportAddress;
enum PeerDisconnectInfo : unsigned int
@ -67,10 +67,10 @@ protected:
TransportAddress m_peer_address;
Network* m_network;
STKHost* m_host;
public:
STKPeer(ENetPeer *enet_peer, Network* network);
STKPeer(ENetPeer *enet_peer, STKHost* host);
~STKPeer();
// ------------------------------------------------------------------------
void sendPacket(NetworkString *data, bool reliable = true);