Use shared_ptr for protocol to avoid leaking

With weak_ptr it's also possible to auto clear LobbyProtocol when
STKHost is shutdown
This commit is contained in:
Benau 2018-02-18 12:39:05 +08:00
parent bcf8e4e5fe
commit 0a5c1a69c7
27 changed files with 144 additions and 147 deletions

View File

@ -161,7 +161,7 @@ bool LocalPlayerController::action(PlayerAction action, int value,
NetworkConfig::get()->isClient() && NetworkConfig::get()->isClient() &&
!RewindManager::get()->isRewinding() ) !RewindManager::get()->isRewinding() )
{ {
GameProtocol::getInstance() GameProtocol::lock()
->controllerAction(m_kart->getWorldKartId(), ->controllerAction(m_kart->getWorldKartId(),
action, value, action, value,
m_steer_val_l, m_steer_val_r); m_steer_val_l, m_steer_val_r);

View File

@ -262,8 +262,7 @@ void WorldStatus::updateTime(const float dt)
if (!m_server_is_ready) return; if (!m_server_is_ready) return;
m_phase = READY_PHASE; m_phase = READY_PHASE;
Protocol *p = LobbyProtocol::get(); auto cl = LobbyProtocol::get<ClientLobby>();
ClientLobby *cl = dynamic_cast<ClientLobby*>(p);
if (cl) if (cl)
cl->startingRaceNow(); cl->startingRaceNow();
return; // Don't increase time return; // Don't increase time

View File

@ -78,23 +78,19 @@ void* NetworkConsole::mainLoop(void* data)
} }
else if (str == "start" && NetworkConfig::get()->isServer()) else if (str == "start" && NetworkConfig::get()->isServer())
{ {
ServerLobby* protocol = auto sl = LobbyProtocol::get<ServerLobby>();
dynamic_cast<ServerLobby*>(LobbyProtocol::get()); sl->signalRaceStartToClients();
protocol->signalRaceStartToClients();
} }
else if (str == "selection" && NetworkConfig::get()->isServer()) else if (str == "selection" && NetworkConfig::get()->isServer())
{ {
ServerLobby* protocol = auto sl = LobbyProtocol::get<ServerLobby>();
dynamic_cast<ServerLobby*>(LobbyProtocol::get()); sl->startSelection();
protocol->startSelection();
} }
else if (str == "select" && NetworkConfig::get()->isClient()) else if (str == "select" && NetworkConfig::get()->isClient())
{ {
std::string str2; std::string str2;
getline(std::cin, str2); getline(std::cin, str2);
ServerLobby* protocol = auto clrp = LobbyProtocol::get<ClientLobby>();
dynamic_cast<ServerLobby*>(LobbyProtocol::get());
ClientLobby* clrp = dynamic_cast<ClientLobby*>(protocol);
std::vector<NetworkPlayerProfile*> players = std::vector<NetworkPlayerProfile*> players =
STKHost::get()->getMyPlayerProfiles(); STKHost::get()->getMyPlayerProfiles();
// For now send a vote for each local player // For now send a vote for each local player
@ -109,9 +105,7 @@ void* NetworkConsole::mainLoop(void* data)
std::cout << "Vote for ? (track/laps/reversed/major/minor/race#) :"; std::cout << "Vote for ? (track/laps/reversed/major/minor/race#) :";
std::string str2; std::string str2;
getline(std::cin, str2); getline(std::cin, str2);
LobbyProtocol* protocol = LobbyProtocol::get(); auto clrp = LobbyProtocol::get<ClientLobby>();
ClientLobby* clrp =
dynamic_cast<ClientLobby*>(protocol);
std::vector<NetworkPlayerProfile*> players = std::vector<NetworkPlayerProfile*> players =
STKHost::get()->getMyPlayerProfiles(); STKHost::get()->getMyPlayerProfiles();
if (str2 == "track") if (str2 == "track")
@ -164,14 +158,13 @@ void* NetworkConsole::mainLoop(void* data)
} }
} // while !stop } // while !stop
Protocol *p = new StopServer(); auto p = std::make_shared<StopServer>();
p->requestStart();
while(p->getState() != PROTOCOL_STATE_TERMINATED) while(p->getState() != PROTOCOL_STATE_TERMINATED)
{ {
StkTime::sleep(1); StkTime::sleep(1);
} }
delete p;
main_loop->abort(); main_loop->abort();
return NULL; return NULL;

View File

@ -79,7 +79,7 @@ bool Protocol::checkDataSize(Event* event, unsigned int minimum_size)
*/ */
void Protocol::requestStart() void Protocol::requestStart()
{ {
ProtocolManager::lock()->requestStart(this); ProtocolManager::lock()->requestStart(shared_from_this());
} // requestStart } // requestStart
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -87,7 +87,7 @@ void Protocol::requestStart()
*/ */
void Protocol::requestPause() void Protocol::requestPause()
{ {
ProtocolManager::lock()->requestPause(this); ProtocolManager::lock()->requestPause(shared_from_this());
} // requestPause } // requestPause
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -95,7 +95,7 @@ void Protocol::requestPause()
*/ */
void Protocol::requestUnpause() void Protocol::requestUnpause()
{ {
ProtocolManager::lock()->requestUnpause(this); ProtocolManager::lock()->requestUnpause(shared_from_this());
} // requestUnpause } // requestUnpause
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -103,7 +103,7 @@ void Protocol::requestUnpause()
*/ */
void Protocol::requestTerminate() void Protocol::requestTerminate()
{ {
ProtocolManager::lock()->requestTerminate(this); ProtocolManager::lock()->requestTerminate(shared_from_this());
} // requestTerminate } // requestTerminate
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -27,6 +27,7 @@
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/types.hpp" #include "utils/types.hpp"
#include <memory>
#include <stddef.h> #include <stddef.h>
class Event; class Event;
@ -90,7 +91,8 @@ public:
* to make any network job. * to make any network job.
* \ingroup network * \ingroup network
*/ */
class Protocol : public NoCopy class Protocol : public std::enable_shared_from_this<Protocol>,
public NoCopy
{ {
LEAK_CHECK() LEAK_CHECK()
protected: protected:

View File

@ -99,8 +99,6 @@ ProtocolManager::~ProtocolManager()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ProtocolManager::OneProtocolType::abort() void ProtocolManager::OneProtocolType::abort()
{ {
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
delete m_protocols.getData()[i];
m_protocols.getData().clear(); m_protocols.getData().clear();
} // OneProtocolType::abort } // OneProtocolType::abort
@ -143,7 +141,7 @@ void ProtocolManager::propagateEvent(Event* event)
* \param protocol : A pointer to the protocol to start * \param protocol : A pointer to the protocol to start
* \return The unique id of the protocol that is being started. * \return The unique id of the protocol that is being started.
*/ */
void ProtocolManager::requestStart(Protocol* protocol) void ProtocolManager::requestStart(std::shared_ptr<Protocol> protocol)
{ {
// create the request // create the request
ProtocolRequest req(PROTOCOL_REQUEST_START, protocol); ProtocolRequest req(PROTOCOL_REQUEST_START, protocol);
@ -159,7 +157,7 @@ void ProtocolManager::requestStart(Protocol* protocol)
* thread-safe. * thread-safe.
* \param protocol : A pointer to the protocol to pause * \param protocol : A pointer to the protocol to pause
*/ */
void ProtocolManager::requestPause(Protocol* protocol) void ProtocolManager::requestPause(std::shared_ptr<Protocol> protocol)
{ {
if (!protocol) if (!protocol)
return; return;
@ -177,12 +175,12 @@ void ProtocolManager::requestPause(Protocol* protocol)
* thread-safe. * thread-safe.
* \param protocol : A pointer to the protocol to unpause * \param protocol : A pointer to the protocol to unpause
*/ */
void ProtocolManager::requestUnpause(Protocol* protocol) void ProtocolManager::requestUnpause(std::shared_ptr<Protocol> protocol)
{ {
if (!protocol) if (!protocol)
return; return;
// create the request // create the request
ProtocolRequest req(PROTOCOL_REQUEST_UNPAUSE, protocol);; ProtocolRequest req(PROTOCOL_REQUEST_UNPAUSE, protocol);
// add it to the request stack // add it to the request stack
m_requests.lock(); m_requests.lock();
m_requests.getData().push_back(req); m_requests.getData().push_back(req);
@ -195,7 +193,7 @@ void ProtocolManager::requestUnpause(Protocol* protocol)
* thread-safe. * thread-safe.
* \param protocol : A pointer to the protocol that is finished * \param protocol : A pointer to the protocol that is finished
*/ */
void ProtocolManager::requestTerminate(Protocol* protocol) void ProtocolManager::requestTerminate(std::shared_ptr<Protocol> protocol)
{ {
if (!protocol) if (!protocol)
return; return;
@ -222,7 +220,7 @@ void ProtocolManager::requestTerminate(Protocol* protocol)
* Add the protocol info to the m_protocols vector. * Add the protocol info to the m_protocols vector.
* \param protocol : ProtocolInfo to start. * \param protocol : ProtocolInfo to start.
*/ */
void ProtocolManager::startProtocol(Protocol *protocol) void ProtocolManager::startProtocol(std::shared_ptr<Protocol> protocol)
{ {
assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id()); assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id());
OneProtocolType &opt = m_all_protocols[protocol->getProtocolType()]; OneProtocolType &opt = m_all_protocols[protocol->getProtocolType()];
@ -242,7 +240,7 @@ void ProtocolManager::startProtocol(Protocol *protocol)
* Pauses a protocol and tells it that it's being paused. * Pauses a protocol and tells it that it's being paused.
* \param protocol : Protocol to pause. * \param protocol : Protocol to pause.
*/ */
void ProtocolManager::pauseProtocol(Protocol *protocol) void ProtocolManager::pauseProtocol(std::shared_ptr<Protocol> protocol)
{ {
assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id()); assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id());
assert(protocol->getState() == PROTOCOL_STATE_RUNNING); assert(protocol->getState() == PROTOCOL_STATE_RUNNING);
@ -259,7 +257,7 @@ void ProtocolManager::pauseProtocol(Protocol *protocol)
* Unpauses a protocol and notifies it. * Unpauses a protocol and notifies it.
* \param protocol : Protocol to unpause. * \param protocol : Protocol to unpause.
*/ */
void ProtocolManager::unpauseProtocol(Protocol *protocol) void ProtocolManager::unpauseProtocol(std::shared_ptr<Protocol> protocol)
{ {
assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id()); assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id());
assert(protocol->getState() == PROTOCOL_STATE_PAUSED); assert(protocol->getState() == PROTOCOL_STATE_PAUSED);
@ -274,10 +272,9 @@ void ProtocolManager::unpauseProtocol(Protocol *protocol)
* Note that the protocol is not deleted. * Note that the protocol is not deleted.
* \param p The protocol to be removed. * \param p The protocol to be removed.
*/ */
void ProtocolManager::OneProtocolType::removeProtocol(Protocol *p) void ProtocolManager::OneProtocolType::removeProtocol(std::shared_ptr<Protocol> p)
{ {
std::vector<Protocol*>::iterator i = auto i = std::find(m_protocols.getData().begin(),
std::find(m_protocols.getData().begin(),
m_protocols.getData().end(), p); m_protocols.getData().end(), p);
if (i == m_protocols.getData().end()) if (i == m_protocols.getData().end())
{ {
@ -296,7 +293,7 @@ void ProtocolManager::OneProtocolType::removeProtocol(Protocol *p)
* Remove a protocol from the protocols vector. * Remove a protocol from the protocols vector.
* \param protocol : Protocol concerned. * \param protocol : Protocol concerned.
*/ */
void ProtocolManager::terminateProtocol(Protocol *protocol) void ProtocolManager::terminateProtocol(std::shared_ptr<Protocol> protocol)
{ {
assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id()); assert(std::this_thread::get_id() == m_asynchronous_update_thread.get_id());
@ -551,7 +548,7 @@ void ProtocolManager::asynchronousUpdate()
* \param type : The type of the protocol. * \param type : The type of the protocol.
* \return The protocol that matches the given type. * \return The protocol that matches the given type.
*/ */
Protocol* ProtocolManager::getProtocol(ProtocolType type) std::shared_ptr<Protocol> ProtocolManager::getProtocol(ProtocolType type)
{ {
OneProtocolType &opt = m_all_protocols[type]; OneProtocolType &opt = m_all_protocols[type];
if (opt.isEmpty()) return NULL; if (opt.isEmpty()) return NULL;

View File

@ -67,10 +67,10 @@ public:
ProtocolRequestType m_type; ProtocolRequestType m_type;
/** The concerned protocol information. */ /** The concerned protocol information. */
Protocol *m_protocol; std::shared_ptr<Protocol> m_protocol;
public: public:
ProtocolRequest(ProtocolRequestType type, Protocol *protocol) ProtocolRequest(ProtocolRequestType type, std::shared_ptr<Protocol> protocol)
{ {
m_type = type; m_type = type;
m_protocol = protocol; m_protocol = protocol;
@ -80,7 +80,7 @@ public:
ProtocolRequestType getType() const { return m_type; } ProtocolRequestType getType() const { return m_type; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the protocol for this request. */ /** Returns the protocol for this request. */
Protocol *getProtocol() { return m_protocol; } std::shared_ptr<Protocol> getProtocol() { return m_protocol; }
}; // class ProtocolRequest; }; // class ProtocolRequest;
// ============================================================================ // ============================================================================
@ -144,9 +144,9 @@ private:
class OneProtocolType class OneProtocolType
{ {
private: private:
Synchronised< std::vector<Protocol*> > m_protocols; Synchronised< std::vector<std::shared_ptr<Protocol> > > m_protocols;
public: public:
void removeProtocol(Protocol *p); void removeProtocol(std::shared_ptr<Protocol> p);
void requestTerminateAll(); void requestTerminateAll();
bool notifyEvent(Event *event); bool notifyEvent(Event *event);
void update(float dt, bool async); void update(float dt, bool async);
@ -154,7 +154,8 @@ private:
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Returns the first protocol of a given type. It is assumed that /** Returns the first protocol of a given type. It is assumed that
* there is a protocol of that type. */ * there is a protocol of that type. */
Protocol *getFirstProtocol() { return m_protocols.getData()[0]; } std::shared_ptr<Protocol> getFirstProtocol()
{ return m_protocols.getData()[0]; }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Returns if this protocol class handles connect events. Protocols /** Returns if this protocol class handles connect events. Protocols
* of the same class either all handle a connect event, or none, so * of the same class either all handle a connect event, or none, so
@ -180,7 +181,7 @@ private:
/** Locks access to this list of all protocols of a certain type. */ /** Locks access to this list of all protocols of a certain type. */
void unlock() { m_protocols.unlock(); } void unlock() { m_protocols.unlock(); }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
void addProtocol(Protocol *p) void addProtocol(std::shared_ptr<Protocol> p)
{ {
m_protocols.getData().push_back(p); m_protocols.getData().push_back(p);
} // addProtocol } // addProtocol
@ -222,11 +223,11 @@ private:
bool sendEvent(Event* event); bool sendEvent(Event* event);
virtual void startProtocol(Protocol *protocol); virtual void startProtocol(std::shared_ptr<Protocol> protocol);
virtual void terminateProtocol(Protocol *protocol); virtual void terminateProtocol(std::shared_ptr<Protocol> protocol);
virtual void asynchronousUpdate(); virtual void asynchronousUpdate();
virtual void pauseProtocol(Protocol *protocol); virtual void pauseProtocol(std::shared_ptr<Protocol> protocol);
virtual void unpauseProtocol(Protocol *protocol); virtual void unpauseProtocol(std::shared_ptr<Protocol> protocol);
public: public:
// =========================================== // ===========================================
@ -235,11 +236,11 @@ public:
virtual ~ProtocolManager(); virtual ~ProtocolManager();
void abort(); void abort();
void propagateEvent(Event* event); void propagateEvent(Event* event);
Protocol* getProtocol(ProtocolType type); std::shared_ptr<Protocol> getProtocol(ProtocolType type);
void requestStart(Protocol* protocol); void requestStart(std::shared_ptr<Protocol> protocol);
void requestPause(Protocol* protocol); void requestPause(std::shared_ptr<Protocol> protocol);
void requestUnpause(Protocol* protocol); void requestUnpause(std::shared_ptr<Protocol> protocol);
void requestTerminate(Protocol* protocol); void requestTerminate(std::shared_ptr<Protocol> protocol);
void findAndTerminate(ProtocolType type); void findAndTerminate(ProtocolType type);
void update(float dt); void update(float dt);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -357,8 +357,7 @@ void ClientLobby::update(float dt)
screen->push(); screen->push();
m_state = SELECTING_KARTS; m_state = SELECTING_KARTS;
Protocol *p = new LatencyProtocol(); std::make_shared<LatencyProtocol>()->requestStart();
p->requestStart();
Log::info("LobbyProtocol", "LatencyProtocol started."); Log::info("LobbyProtocol", "LatencyProtocol started.");
} }
break; break;
@ -370,7 +369,7 @@ void ClientLobby::update(float dt)
break; break;
case DONE: case DONE:
m_state = EXITING; m_state = EXITING;
ProtocolManager::lock()->requestTerminate(this); ProtocolManager::lock()->requestTerminate(shared_from_this());
break; break;
case EXITING: case EXITING:
break; break;

View File

@ -40,7 +40,6 @@ ConnectToPeer::ConnectToPeer(uint32_t peer_id) : Protocol(PROTOCOL_CONNECTION)
m_peer_address.clear(); m_peer_address.clear();
m_peer_id = peer_id; m_peer_id = peer_id;
m_state = NONE; m_state = NONE;
m_current_protocol = NULL;
m_is_lan = false; m_is_lan = false;
setHandleConnections(true); setHandleConnections(true);
} // ConnectToPeer(peer_id) } // ConnectToPeer(peer_id)
@ -56,7 +55,6 @@ ConnectToPeer::ConnectToPeer(const TransportAddress &address)
// We don't need to find the peer address, so we can start // We don't need to find the peer address, so we can start
// with the state when we found the peer address. // with the state when we found the peer address.
m_state = RECEIVED_PEER_ADDRESS; m_state = RECEIVED_PEER_ADDRESS;
m_current_protocol = NULL;
m_is_lan = true; m_is_lan = true;
setHandleConnections(true); setHandleConnections(true);
} // ConnectToPeers(TransportAddress) } // ConnectToPeers(TransportAddress)
@ -99,7 +97,7 @@ void ConnectToPeer::asynchronousUpdate()
{ {
case NONE: case NONE:
{ {
m_current_protocol = new GetPeerAddress(m_peer_id, this); m_current_protocol = std::make_shared<GetPeerAddress>(m_peer_id, this);
m_current_protocol->requestStart(); m_current_protocol->requestStart();
// Pause this protocol till we receive an answer // Pause this protocol till we receive an answer
@ -118,8 +116,7 @@ void ConnectToPeer::asynchronousUpdate()
m_state = DONE; m_state = DONE;
break; break;
} }
delete m_current_protocol; m_current_protocol = nullptr;
m_current_protocol = 0;
// Now we know the peer address. If it's a non-local host, start // Now we know the peer address. If it's a non-local host, start
// the Ping protocol to keep the port available. We can't rely on // the Ping protocol to keep the port available. We can't rely on
@ -130,7 +127,7 @@ void ConnectToPeer::asynchronousUpdate()
NetworkConfig::get()->getMyAddress().getIP() ) || NetworkConfig::get()->getMyAddress().getIP() ) ||
NetworkConfig::m_disable_lan ) NetworkConfig::m_disable_lan )
{ {
m_current_protocol = new PingProtocol(m_peer_address, m_current_protocol = std::make_shared<PingProtocol>(m_peer_address,
/*time-between-ping*/2.0); /*time-between-ping*/2.0);
ProtocolManager::lock()->requestStart(m_current_protocol); ProtocolManager::lock()->requestStart(m_current_protocol);
m_state = CONNECTING; m_state = CONNECTING;
@ -202,7 +199,7 @@ void ConnectToPeer::asynchronousUpdate()
{ {
// Kill the ping protocol because we're connected // Kill the ping protocol because we're connected
m_current_protocol->requestTerminate(); m_current_protocol->requestTerminate();
m_current_protocol = NULL; m_current_protocol = nullptr;
} }
m_state = DONE; m_state = DONE;
break; break;

View File

@ -34,7 +34,7 @@ protected:
uint32_t m_peer_id; uint32_t m_peer_id;
/** Pointer to the protocol which is monitored for state changes. */ /** Pointer to the protocol which is monitored for state changes. */
Protocol *m_current_protocol; std::shared_ptr<Protocol> m_current_protocol;
/** True if this is a LAN connection. */ /** True if this is a LAN connection. */
bool m_is_lan; bool m_is_lan;

View File

@ -82,7 +82,7 @@ ConnectToServer::~ConnectToServer()
void ConnectToServer::setup() void ConnectToServer::setup()
{ {
Log::info("ConnectToServer", "SETUP"); Log::info("ConnectToServer", "SETUP");
m_current_protocol = NULL; m_current_protocol = nullptr;
// In case of LAN we already have the server's and our ip address, // In case of LAN we already have the server's and our ip address,
// so we can immediately start requesting a connection. // so we can immediately start requesting a connection.
m_state = NetworkConfig::get()->isLAN() ? GOT_SERVER_ADDRESS : NONE; m_state = NetworkConfig::get()->isLAN() ? GOT_SERVER_ADDRESS : NONE;
@ -108,7 +108,7 @@ void ConnectToServer::asynchronousUpdate()
Log::info("ConnectToServer", "Protocol starting"); Log::info("ConnectToServer", "Protocol starting");
// This protocol will write the public address of this // This protocol will write the public address of this
// instance to STKHost. // instance to STKHost.
m_current_protocol = new GetPublicAddress(this); m_current_protocol = std::make_shared<GetPublicAddress>(this);
m_current_protocol->requestStart(); m_current_protocol->requestStart();
// This protocol will be unpaused in the callback from // This protocol will be unpaused in the callback from
// GetPublicAddress // GetPublicAddress
@ -118,8 +118,8 @@ void ConnectToServer::asynchronousUpdate()
} }
case GETTING_SELF_ADDRESS: case GETTING_SELF_ADDRESS:
{ {
delete m_current_protocol; // delete GetPublicAddress // drop GetPublicAddress
m_current_protocol = NULL; m_current_protocol = nullptr;
registerWithSTKServer(); // Register us with STK server registerWithSTKServer(); // Register us with STK server
@ -139,8 +139,7 @@ void ConnectToServer::asynchronousUpdate()
case GOT_SERVER_ADDRESS: case GOT_SERVER_ADDRESS:
{ {
assert(!m_quick_join); assert(!m_quick_join);
delete m_current_protocol; m_current_protocol = nullptr;
m_current_protocol = NULL;
Log::info("ConnectToServer", "Server's address known"); Log::info("ConnectToServer", "Server's address known");
// we're in the same lan (same public ip address) !! // we're in the same lan (same public ip address) !!
@ -151,7 +150,7 @@ void ConnectToServer::asynchronousUpdate()
"Server appears to be in the same LAN."); "Server appears to be in the same LAN.");
} }
m_state = REQUESTING_CONNECTION; m_state = REQUESTING_CONNECTION;
m_current_protocol = new RequestConnection(m_server_id); m_current_protocol = std::make_shared<RequestConnection>(m_server_id);
m_current_protocol->requestStart(); m_current_protocol->requestStart();
break; break;
} }
@ -160,8 +159,7 @@ void ConnectToServer::asynchronousUpdate()
if (!m_current_protocol || if (!m_current_protocol ||
m_current_protocol->getState() == PROTOCOL_STATE_TERMINATED) m_current_protocol->getState() == PROTOCOL_STATE_TERMINATED)
{ {
delete m_current_protocol; m_current_protocol = nullptr;
m_current_protocol = NULL;
// Server knows we want to connect // Server knows we want to connect
Log::info("ConnectToServer", "Connection request made"); Log::info("ConnectToServer", "Connection request made");
if (m_server_address.getIP() == 0 || if (m_server_address.getIP() == 0 ||
@ -171,7 +169,7 @@ void ConnectToServer::asynchronousUpdate()
m_state = HIDING_ADDRESS; m_state = HIDING_ADDRESS;
Log::error("ConnectToServer", "Server address is %s", Log::error("ConnectToServer", "Server address is %s",
m_server_address.toString().c_str()); m_server_address.toString().c_str());
m_current_protocol = new HidePublicAddress(); m_current_protocol = std::make_shared<HidePublicAddress>();
m_current_protocol->requestStart(); m_current_protocol->requestStart();
return; return;
} }
@ -187,7 +185,7 @@ void ConnectToServer::asynchronousUpdate()
else else
{ {
m_state = CONNECTING; m_state = CONNECTING;
m_current_protocol = new PingProtocol(m_server_address, 2.0); m_current_protocol = std::make_shared<PingProtocol>(m_server_address, 2.0);
m_current_protocol->requestStart(); m_current_protocol->requestStart();
} }
} }
@ -212,12 +210,11 @@ void ConnectToServer::asynchronousUpdate()
// Kill the ping protocol because we're connected // Kill the ping protocol because we're connected
m_current_protocol->requestTerminate(); m_current_protocol->requestTerminate();
} }
delete m_current_protocol; m_current_protocol = nullptr;
m_current_protocol = NULL;
// LAN networking does not use the stk server tables. // LAN networking does not use the stk server tables.
if(NetworkConfig::get()->isWAN()) if(NetworkConfig::get()->isWAN())
{ {
m_current_protocol = new HidePublicAddress(); m_current_protocol = std::make_shared<HidePublicAddress>();
m_current_protocol->requestStart(); m_current_protocol->requestStart();
} }
m_state = HIDING_ADDRESS; m_state = HIDING_ADDRESS;
@ -230,18 +227,16 @@ void ConnectToServer::asynchronousUpdate()
{ {
if(m_current_protocol) if(m_current_protocol)
{ {
delete m_current_protocol; m_current_protocol = nullptr;
m_current_protocol = NULL;
Log::info("ConnectToServer", "Address hidden"); Log::info("ConnectToServer", "Address hidden");
} }
m_state = DONE; m_state = DONE;
// lobby room protocol if we're connected only // lobby room protocol if we're connected only
if(STKHost::get()->getPeers()[0]->isConnected()) if(STKHost::get()->getPeers()[0]->isConnected())
{ {
ClientLobby *p = auto cl = LobbyProtocol::create<ClientLobby>();
LobbyProtocol::create<ClientLobby>(); cl->setAddress(m_server_address);
p->setAddress(m_server_address); cl->requestStart();
p->requestStart();
} }
} }
break; break;

View File

@ -32,7 +32,7 @@ private:
uint32_t m_host_id; uint32_t m_host_id;
/** Protocol currently being monitored. */ /** Protocol currently being monitored. */
Protocol *m_current_protocol; std::shared_ptr<Protocol> m_current_protocol;
bool m_quick_join; bool m_quick_join;
/** State for finite state machine. */ /** State for finite state machine. */

View File

@ -32,6 +32,21 @@
#include "network/stk_peer.hpp" #include "network/stk_peer.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
// ============================================================================
std::weak_ptr<GameProtocol> GameProtocol::m_game_protocol;
// ============================================================================
std::shared_ptr<GameProtocol> GameProtocol::createInstance()
{
if (!emptyInstance())
{
Log::fatal("GameProtocol", "Create only 1 instance of GameProtocol!");
return NULL;
}
auto gm = std::make_shared<GameProtocol>();
m_game_protocol = gm;
return gm;
} // createInstance
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Constructor. Allocates the buffer for events to send to the server. */ /** Constructor. Allocates the buffer for events to send to the server. */
GameProtocol::GameProtocol() GameProtocol::GameProtocol()

View File

@ -34,7 +34,6 @@ class STKPeer;
class GameProtocol : public Protocol class GameProtocol : public Protocol
, public EventRewinder , public EventRewinder
, public Singleton<GameProtocol>
{ {
private: private:
@ -69,6 +68,7 @@ private:
void handleControllerAction(Event *event); void handleControllerAction(Event *event);
void handleState(Event *event); void handleState(Event *event);
void handleAdjustTime(Event *event); void handleAdjustTime(Event *event);
static std::weak_ptr<GameProtocol> m_game_protocol;
public: public:
GameProtocol(); GameProtocol();
virtual ~GameProtocol(); virtual ~GameProtocol();
@ -90,6 +90,18 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void asynchronousUpdate() OVERRIDE {} virtual void asynchronousUpdate() OVERRIDE {}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
static std::shared_ptr<GameProtocol> createInstance();
// ------------------------------------------------------------------------
static bool emptyInstance()
{
return m_game_protocol.expired();
} // emptyInstance
// ------------------------------------------------------------------------
static std::shared_ptr<GameProtocol> lock()
{
return m_game_protocol.lock();
} // lock
}; // class GameProtocol }; // class GameProtocol
#endif // GAME_PROTOCOL_HPP #endif // GAME_PROTOCOL_HPP

View File

@ -33,7 +33,7 @@
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
#include "states_screens/state_manager.hpp" #include "states_screens/state_manager.hpp"
LobbyProtocol *LobbyProtocol::m_lobby = NULL; std::weak_ptr<LobbyProtocol> LobbyProtocol::m_lobby;
LobbyProtocol::LobbyProtocol(CallbackObject* callback_object) LobbyProtocol::LobbyProtocol(CallbackObject* callback_object)
: Protocol(PROTOCOL_LOBBY_ROOM, callback_object) : Protocol(PROTOCOL_LOBBY_ROOM, callback_object)
@ -125,8 +125,8 @@ void LobbyProtocol::loadWorld()
// Load the actual world. // Load the actual world.
m_game_setup->getRaceConfig()->loadWorld(); m_game_setup->getRaceConfig()->loadWorld();
World::getWorld()->setNetworkWorld(true); World::getWorld()->setNetworkWorld(true);
GameProtocol::getInstance()->requestStart(); GameProtocol::createInstance()->requestStart();
(new GameEventsProtocol())->requestStart(); std::make_shared<GameEventsProtocol>()->requestStart();
} // loadWorld } // loadWorld

View File

@ -63,28 +63,33 @@ public:
}; };
protected: protected:
static LobbyProtocol *m_lobby; static std::weak_ptr<LobbyProtocol> m_lobby;
/** The game setup. */ /** The game setup. */
GameSetup* m_game_setup; GameSetup* m_game_setup;
public: public:
/** Creates either a client or server lobby protocol as a singleton. */ /** Creates either a client or server lobby protocol as a singleton. */
template<typename S> static S* create() template<typename singleton> static std::shared_ptr<singleton> create()
{ {
assert(m_lobby == NULL); assert(m_lobby.expired());
m_lobby = new S(); auto ret = std::make_shared<singleton>();
return dynamic_cast<S*>(m_lobby); m_lobby = ret;
return std::dynamic_pointer_cast<singleton>(ret);
} // create } // create
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the singleton client or server lobby protocol. */ /** Returns the singleton client or server lobby protocol. */
static LobbyProtocol *get() template<class T> static std::shared_ptr<T> get()
{ {
assert(m_lobby); if (std::shared_ptr<LobbyProtocol> lp = m_lobby.lock())
return m_lobby; {
std::shared_ptr<T> new_type = std::dynamic_pointer_cast<T>(lp);
if (new_type)
return new_type;
}
return nullptr;
} // get } // get
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -115,7 +115,7 @@ void ServerLobby::setup()
m_state = NetworkConfig::get()->isLAN() ? ACCEPTING_CLIENTS m_state = NetworkConfig::get()->isLAN() ? ACCEPTING_CLIENTS
: INIT_WAN; : INIT_WAN;
m_selection_enabled = false; m_selection_enabled = false;
m_current_protocol = NULL; m_current_protocol = nullptr;
Log::info("ServerLobby", "Starting the protocol."); Log::info("ServerLobby", "Starting the protocol.");
// Initialise the data structures to detect if all clients and // Initialise the data structures to detect if all clients and
@ -202,7 +202,7 @@ void ServerLobby::update(float dt)
{ {
case INIT_WAN: case INIT_WAN:
// Start the protocol to find the public ip address. // Start the protocol to find the public ip address.
m_current_protocol = new GetPublicAddress(this); m_current_protocol = std::make_shared<GetPublicAddress>(this);
m_current_protocol->requestStart(); m_current_protocol->requestStart();
m_state = GETTING_PUBLIC_ADDRESS; m_state = GETTING_PUBLIC_ADDRESS;
// The callback from GetPublicAddress will wake this protocol up // The callback from GetPublicAddress will wake this protocol up
@ -212,7 +212,7 @@ void ServerLobby::update(float dt)
{ {
Log::debug("ServerLobby", "Public address known."); Log::debug("ServerLobby", "Public address known.");
// Free GetPublicAddress protocol // Free GetPublicAddress protocol
delete m_current_protocol; m_current_protocol = nullptr;
// Register this server with the STK server. This will block // Register this server with the STK server. This will block
// this thread, but there is no need for the protocol manager // this thread, but there is no need for the protocol manager
@ -420,8 +420,7 @@ void ServerLobby::startSelection(const Event *event)
m_state = SELECTING; m_state = SELECTING;
WaitingForOthersScreen::getInstance()->push(); WaitingForOthersScreen::getInstance()->push();
Protocol *p = new LatencyProtocol(); std::make_shared<LatencyProtocol>()->requestStart();
p->requestStart();
Log::info("LobbyProtocol", "LatencyProtocol started."); Log::info("LobbyProtocol", "LatencyProtocol started.");
} // startSelection } // startSelection
@ -468,8 +467,7 @@ void ServerLobby::checkIncomingConnectionRequests()
users_xml->getNode(i)->get("id", &id); users_xml->getNode(i)->get("id", &id);
Log::debug("ServerLobby", Log::debug("ServerLobby",
"User with id %d wants to connect.", id); "User with id %d wants to connect.", id);
Protocol *p = new ConnectToPeer(id); std::make_shared<ConnectToPeer>(id)->requestStart();
p->requestStart();
} }
delete request; delete request;
} // checkIncomingConnectionRequests } // checkIncomingConnectionRequests

View File

@ -54,7 +54,7 @@ private:
* seconds), which is the real time at which the server should start. */ * seconds), which is the real time at which the server should start. */
double m_server_delay; double m_server_delay;
Protocol *m_current_protocol; std::shared_ptr<Protocol> m_current_protocol;
bool m_selection_enabled; bool m_selection_enabled;
/** Counts how many players are ready to go on. */ /** Counts how many players are ready to go on. */

View File

@ -73,7 +73,7 @@ bool RaceEventManager::isRaceOver()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void RaceEventManager::kartFinishedRace(AbstractKart *kart, float time) void RaceEventManager::kartFinishedRace(AbstractKart *kart, float time)
{ {
GameEventsProtocol* protocol = static_cast<GameEventsProtocol*>( auto protocol = std::static_pointer_cast<GameEventsProtocol>(
ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS)); ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS));
protocol->kartFinishedRace(kart, time); protocol->kartFinishedRace(kart, time);
} // kartFinishedRace } // kartFinishedRace
@ -89,7 +89,7 @@ void RaceEventManager::collectedItem(Item *item, AbstractKart *kart)
// this is only called in the server // this is only called in the server
assert(NetworkConfig::get()->isServer()); assert(NetworkConfig::get()->isServer());
GameEventsProtocol* protocol = static_cast<GameEventsProtocol*>( auto protocol = std::static_pointer_cast<GameEventsProtocol>(
ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS)); ProtocolManager::lock()->getProtocol(PROTOCOL_GAME_EVENTS));
protocol->collectedItem(item,kart); protocol->collectedItem(item,kart);
} // collectedItem } // collectedItem

View File

@ -191,7 +191,7 @@ void RewindManager::update(float dt)
PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20); PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
// Save state // Save state
GameProtocol::getInstance()->startNewState(); GameProtocol::lock()->startNewState();
AllRewinder::const_iterator rewinder; AllRewinder::const_iterator rewinder;
for(rewinder=m_all_rewinder.begin(); rewinder!=m_all_rewinder.end(); ++rewinder) for(rewinder=m_all_rewinder.begin(); rewinder!=m_all_rewinder.end(); ++rewinder)
{ {
@ -202,14 +202,14 @@ void RewindManager::update(float dt)
// Add to the previously created container // Add to the previously created container
m_rewind_queue.addLocalState(*rewinder, buffer, /*confirmed*/true, m_rewind_queue.addLocalState(*rewinder, buffer, /*confirmed*/true,
World::getWorld()->getTime()); World::getWorld()->getTime());
GameProtocol::getInstance()->addState(buffer); GameProtocol::lock()->addState(buffer);
} // size >= 0 } // size >= 0
else else
delete buffer; // NULL or 0 byte buffer delete buffer; // NULL or 0 byte buffer
} }
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40); PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
GameProtocol::getInstance()->sendState(); GameProtocol::lock()->sendState();
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
m_last_saved_state = time; m_last_saved_state = time;
} // update } // update

View File

@ -257,8 +257,7 @@ STKHost::STKHost(uint32_t server_id, uint32_t host_id)
"an ENet client host."); "an ENet client host.");
} }
Protocol *connect = new ConnectToServer(server_id, host_id); std::make_shared<ConnectToServer>(server_id, host_id)->requestStart();
connect->requestStart();
} // STKHost } // STKHost
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -288,8 +287,7 @@ STKHost::STKHost(const irr::core::stringw &server_name)
} }
startListening(); startListening();
Protocol *p = LobbyProtocol::create<ServerLobby>(); ProtocolManager::lock()->requestStart(LobbyProtocol::create<ServerLobby>());
ProtocolManager::lock()->requestStart(p);
} // STKHost(server_name) } // STKHost(server_name)
@ -608,8 +606,7 @@ void STKHost::handleDirectSocketRequest()
{ {
// In case of a LAN connection, we only allow connections from // In case of a LAN connection, we only allow connections from
// a LAN address (192.168*, ..., and 127.*). // a LAN address (192.168*, ..., and 127.*).
Protocol *c = new ConnectToPeer(sender); std::make_shared<ConnectToPeer>(sender)->requestStart();
c->requestStart();
} }
else else
Log::info("STKHost", "Received unknown command '%s'", Log::info("STKHost", "Received unknown command '%s'",

View File

@ -562,7 +562,7 @@ void RaceManager::startNextRace()
// the world has been setup // the world has been setup
if(NetworkConfig::get()->isNetworking()) if(NetworkConfig::get()->isNetworking())
{ {
LobbyProtocol *lobby = LobbyProtocol::get(); auto lobby = LobbyProtocol::get<LobbyProtocol>();
assert(lobby); assert(lobby);
lobby->finishedLoadingWorld(); lobby->finishedLoadingWorld();
} }

View File

@ -144,9 +144,7 @@ void NetworkKartSelectionScreen::playerConfirm(const int playerID)
} }
if(playerID == PLAYER_ID_GAME_MASTER) // self if(playerID == PLAYER_ID_GAME_MASTER) // self
{ {
auto clrp = LobbyProtocol::get<ClientLobby>();
LobbyProtocol* protocol = LobbyProtocol::get();
ClientLobby *clrp = dynamic_cast<ClientLobby*>(protocol);
assert(clrp); assert(clrp);
// FIXME SPLITSCREEN: we need to supply the global player id of the // FIXME SPLITSCREEN: we need to supply the global player id of the
// player selecting the kart here. For now ... just vote the same kart // player selecting the kart here. For now ... just vote the same kart
@ -196,10 +194,7 @@ void NetworkKartSelectionScreen::playerSelected(uint8_t player_id,
// to the server. // to the server.
if(STKHost::get()->isAuthorisedToControl()) if(STKHost::get()->isAuthorisedToControl())
{ {
Protocol* protocol = ProtocolManager::lock() auto clrp = LobbyProtocol::get<ClientLobby>();
->getProtocol(PROTOCOL_LOBBY_ROOM);
ClientLobby* clrp =
dynamic_cast<ClientLobby*>(protocol);
assert(clrp); assert(clrp);
// FIXME: for now we submit a vote from the authorised user // FIXME: for now we submit a vote from the authorised user
// for the various modes based on the settings in the race manager. // for the various modes based on the settings in the race manager.
@ -214,7 +209,7 @@ void NetworkKartSelectionScreen::playerSelected(uint8_t player_id,
clrp->voteMinor(id, race_manager->getMinorMode()); clrp->voteMinor(id, race_manager->getMinorMode());
clrp->voteReversed(id, race_manager->getReverseTrack()); clrp->voteReversed(id, race_manager->getReverseTrack());
clrp->voteRaceCount(id, 1); clrp->voteRaceCount(id, 1);
clrp->voteLaps(id, 3); clrp->voteLaps(id, 1);
} }
//WaitingForOthersScreen::getInstance()->push(); //WaitingForOthersScreen::getInstance()->push();
//return; //return;
@ -228,10 +223,8 @@ bool NetworkKartSelectionScreen::onEscapePressed()
// then remove the lobby screen (you left the server) // then remove the lobby screen (you left the server)
StateManager::get()->popMenu(); StateManager::get()->popMenu();
ServerSelection::getInstance()->refresh(); ServerSelection::getInstance()->refresh();
Protocol *lobby = LobbyProtocol::get();
// notify the server that we left // notify the server that we left
ClientLobby* clrp = auto clrp = LobbyProtocol::get<ClientLobby>();
dynamic_cast<ClientLobby*>(lobby);
if (clrp) if (clrp)
clrp->leave(); clrp->leave();
return true; // remove the screen return true; // remove the screen

View File

@ -162,8 +162,7 @@ void NetworkingLobby::eventCallback(Widget* widget, const std::string& name,
{ {
if(NetworkConfig::get()->isServer()) if(NetworkConfig::get()->isServer())
{ {
Protocol *p = LobbyProtocol::get(); auto slrp = LobbyProtocol::get<ServerLobby>();
ServerLobby* slrp = dynamic_cast<ServerLobby*>(p);
slrp->startSelection(); slrp->startSelection();
} }
else // client else // client
@ -198,10 +197,9 @@ void NetworkingLobby::tearDown()
bool NetworkingLobby::onEscapePressed() bool NetworkingLobby::onEscapePressed()
{ {
// notify the server that we left // notify the server that we left
ClientLobby* protocol = auto clrp = LobbyProtocol::get<ClientLobby>();
dynamic_cast<ClientLobby*>(LobbyProtocol::get()); if (clrp)
if (protocol) clrp->leave();
protocol->leave();
STKHost::get()->shutdown(); STKHost::get()->shutdown();
return true; // close the screen return true; // close the screen
} // onEscapePressed } // onEscapePressed

View File

@ -149,7 +149,7 @@ void OnlineProfileServers::doQuickPlay()
{ {
delete join_request; delete join_request;
NetworkingLobby::getInstance()->push(); NetworkingLobby::getInstance()->push();
ConnectToServer *cts = new ConnectToServer(server->getServerId(), auto cts = std::make_shared<ConnectToServer>(server->getServerId(),
server->getHostId()); server->getHostId());
ProtocolManager::lock()->requestStart(cts); ProtocolManager::lock()->requestStart(cts);
} }

View File

@ -348,9 +348,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
if (name == "middle") // Continue button (return to server lobby) if (name == "middle") // Continue button (return to server lobby)
{ {
// Signal to the server that this client is back in the lobby now. // Signal to the server that this client is back in the lobby now.
Protocol* protocol = LobbyProtocol::get(); auto clrp = LobbyProtocol::get<ClientLobby>();
ClientLobby* clrp =
dynamic_cast<ClientLobby*>(protocol);
if(clrp) if(clrp)
clrp->doneWithResults(); clrp->doneWithResults();
backToLobby(); backToLobby();

View File

@ -89,10 +89,9 @@ void TracksScreen::eventCallback(Widget* widget, const std::string& name,
{ {
if(STKHost::existHost()) if(STKHost::existHost())
{ {
Protocol* protocol = LobbyProtocol::get(); auto clrp = LobbyProtocol::get<ClientLobby>();
ClientLobby* clrp = // server never shows the track screen.
dynamic_cast<ClientLobby*>(protocol); assert(clrp);
assert(clrp); // server never shows the track screen.
// FIXME SPLITSCREEN: we need to supply the global player id of the // FIXME SPLITSCREEN: we need to supply the global player id of the
// player selecting the track here. For now ... just vote the same // player selecting the track here. For now ... just vote the same
// track for each local player. // track for each local player.
@ -200,11 +199,10 @@ void TracksScreen::buildTrackList()
// First build a list of all tracks to be displayed // First build a list of all tracks to be displayed
// (e.g. exclude arenas, ...) // (e.g. exclude arenas, ...)
bool is_network = (STKHost::existHost()); bool is_network = (STKHost::existHost());
ClientLobby* clrp = NULL; std::shared_ptr<ClientLobby> clrp;
if (is_network) if (is_network)
{ {
Protocol* protocol = LobbyProtocol::get(); clrp = LobbyProtocol::get<ClientLobby>();
clrp = dynamic_cast<ClientLobby*>(protocol);
assert(clrp); assert(clrp);
} }
PtrVector<Track, REF> tracks; PtrVector<Track, REF> tracks;