modifying the protocol system to have bon synchronous and asynchronous updates (required by gui and graphics to avoid crashes because of threads)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13246 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-07-15 14:31:14 +00:00
parent 72dd260bd1
commit 3bb6122f8e
31 changed files with 152 additions and 93 deletions

View File

@ -19,6 +19,7 @@ void NetworkWorld::update(float dt)
ProtocolManager::getInstance()->getProtocol(PROTOCOL_SYNCHRONIZATION));
if (protocol) // if this protocol exists, that's that we play online
{
Log::info("NetworkWorld", "Coutdown value is %d", protocol->getCountdown());
if (protocol->getCountdown() > 0)
{
return;

View File

@ -90,9 +90,13 @@ class Protocol
*/
virtual void unpause();
/*!
* \brief Called by the protocol listener as often as possible. Must be re-defined.
* \brief Called by the protocol listener, synchronously with the main loop. Must be re-defined.
*/
virtual void update() = 0;
/*!
* \brief Called by the protocol listener as often as possible. Must be re-defined.
*/
virtual void asynchronousUpdate() = 0;
/*!
* \brief Called when the protocol is to be killed.
*/

View File

@ -38,6 +38,16 @@ void* protocolManagerUpdate(void* data)
}
return NULL;
}
void* protocolManagerAsynchronousUpdate(void* data)
{
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
while(!manager->exit())
{
manager->asynchronousUpdate();
irr_driver->getDevice()->sleep(20);
}
return NULL;
}
ProtocolManager::ProtocolManager()
{
@ -50,12 +60,15 @@ ProtocolManager::ProtocolManager()
pthread_mutex_lock(&m_exit_mutex); // will let the update function run
/// NOT USED on client but updated in main loop (because of GUI crash)
/// FIXME used on server because mainloop never running
if (NetworkManager::getInstance()->isServer())
{
m_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
pthread_create(m_update_thread, NULL, protocolManagerUpdate, this);
}
// always run this one
m_asynchronous_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
pthread_create(m_asynchronous_update_thread, NULL, protocolManagerAsynchronousUpdate, this);
}
ProtocolManager::~ProtocolManager()
@ -274,6 +287,18 @@ void ProtocolManager::propagateEvent(Event* event)
}
void ProtocolManager::update()
{
// now update all protocols
pthread_mutex_lock(&m_protocols_mutex);
for (unsigned int i = 0; i < m_protocols.size(); i++)
{
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
m_protocols[i].protocol->update();
}
pthread_mutex_unlock(&m_protocols_mutex);
}
void ProtocolManager::asynchronousUpdate()
{
// before updating, notice protocols that they have received information
int size = m_events_to_process.size();
@ -287,16 +312,17 @@ void ProtocolManager::update()
propagateEvent(event);
}
// now update all protocols
// now update all protocols that need to be updated in asynchronous mode
pthread_mutex_lock(&m_protocols_mutex);
for (unsigned int i = 0; i < m_protocols.size(); i++)
{
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
m_protocols[i].protocol->update();
m_protocols[i].protocol->asynchronousUpdate();
}
pthread_mutex_unlock(&m_protocols_mutex);
// process queued events for protocols
// these requests are asynchronous
pthread_mutex_lock(&m_requests_mutex);
for (unsigned int i = 0; i < m_requests.size(); i++)
{

View File

@ -158,10 +158,21 @@ class ProtocolManager : public Singleton<ProtocolManager>
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called by a thread as often as possible.
* This function is not FPS-dependant.
* This function is called by the main loop.
* This function IS FPS-dependant.
*/
virtual void update();
/*!
* \brief Updates the manager.
*
* This function processes the events queue, notifies the concerned
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called in a thread.
* This function IS NOT FPS-dependant.
*/
virtual void asynchronousUpdate();
/*!
* \brief Get the number of protocols running.
@ -296,6 +307,8 @@ class ProtocolManager : public Singleton<ProtocolManager>
/*! Update thread.*/
pthread_t* m_update_thread;
/*! Asynchronous update thread.*/
pthread_t* m_asynchronous_update_thread;
};

View File

@ -15,6 +15,7 @@ class ClientLobbyRoomProtocol : public LobbyRoomProtocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {}
protected:

View File

@ -69,7 +69,7 @@ void ConnectToPeer::setup()
// ----------------------------------------------------------------------------
void ConnectToPeer::update()
void ConnectToPeer::asynchronousUpdate()
{
switch(m_state)
{

View File

@ -31,7 +31,8 @@ class ConnectToPeer : public Protocol, public CallbackObject
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
TransportAddress m_peer_address;

View File

@ -83,7 +83,7 @@ void ConnectToServer::setup()
// ----------------------------------------------------------------------------
void ConnectToServer::update()
void ConnectToServer::asynchronousUpdate()
{
switch(m_state)
{

View File

@ -32,7 +32,8 @@ class ConnectToServer : public Protocol, public CallbackObject
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
TransportAddress m_server_address;

View File

@ -44,7 +44,7 @@ void GetPeerAddress::setup()
m_state = NONE;
}
void GetPeerAddress::update()
void GetPeerAddress::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -29,7 +29,8 @@ class GetPeerAddress : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
void setPeerID(uint32_t m_peer_id);
protected:

View File

@ -56,7 +56,7 @@ void GetPublicAddress::setup()
m_state = NOTHING_DONE;
}
void GetPublicAddress::update()
void GetPublicAddress::asynchronousUpdate()
{
if (m_state == NOTHING_DONE)
{

View File

@ -30,7 +30,8 @@ class GetPublicAddress : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
enum STATE

View File

@ -41,7 +41,7 @@ void HidePublicAddress::setup()
m_state = NONE;
}
void HidePublicAddress::update()
void HidePublicAddress::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -30,7 +30,8 @@ class HidePublicAddress : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:

View File

@ -40,7 +40,7 @@ void PingProtocol::setup()
m_last_ping_time = 0;
}
void PingProtocol::update()
void PingProtocol::asynchronousUpdate()
{
if (Time::getRealTime() > m_last_ping_time+m_delay_between_pings)
{

View File

@ -12,7 +12,8 @@ class PingProtocol : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
TransportAddress m_ping_dst;

View File

@ -42,7 +42,7 @@ void QuickJoinProtocol::setup()
m_state = NONE;
}
void QuickJoinProtocol::update()
void QuickJoinProtocol::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -12,7 +12,8 @@ class QuickJoinProtocol : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
uint32_t* m_server_id;

View File

@ -41,7 +41,7 @@ void RequestConnection::setup()
m_state = NONE;
}
void RequestConnection::update()
void RequestConnection::asynchronousUpdate()
{
switch (m_state)
{

View File

@ -11,7 +11,8 @@ class RequestConnection : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
uint32_t m_server_id;

View File

@ -12,6 +12,7 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {};
void startGame();

View File

@ -41,7 +41,7 @@ void ShowPublicAddress::setup()
m_state = NONE;
}
void ShowPublicAddress::update()
void ShowPublicAddress::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -30,7 +30,8 @@ class ShowPublicAddress : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:

View File

@ -26,6 +26,7 @@ class StartGameProtocol : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void asynchronousUpdate() {}
void ready();

View File

@ -40,7 +40,7 @@ void StartServer::setup()
m_state = NONE;
}
void StartServer::update()
void StartServer::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -15,7 +15,8 @@ class StartServer : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
enum STATE

View File

@ -40,7 +40,7 @@ void StopServer::setup()
m_state = NONE;
}
void StopServer::update()
void StopServer::asynchronousUpdate()
{
if (m_state == NONE)
{

View File

@ -15,7 +15,8 @@ class StopServer : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
enum STATE

View File

@ -103,7 +103,7 @@ void SynchronizationProtocol::setup()
//-----------------------------------------------------------------------------
void SynchronizationProtocol::update()
void SynchronizationProtocol::asynchronousUpdate()
{
static double timer = Time::getRealTime();
double current_time = Time::getRealTime();
@ -123,7 +123,7 @@ void SynchronizationProtocol::update()
if (m_countdown_activated)
{
ns.ai16(m_countdown);
Log::info("SynchronizationProtocol", "Countdown value : %u", m_countdown);
Log::info("SynchronizationProtocol", "Countdown value : %d", m_countdown);
}
Log::verbose("SynchronizationProtocol", "Added sequence number %u for peer %d", m_pings[i].size(), i);
timer = current_time;
@ -131,7 +131,7 @@ void SynchronizationProtocol::update()
m_listener->sendMessage(this, peers[i], ns, false);
m_pings_count[i]++;
}
Log::info("SynchronizationProtocol", "Countdown remaining : %u", m_countdown);
Log::info("SynchronizationProtocol", "Countdown remaining : %d", m_countdown);
}
}

View File

@ -13,7 +13,8 @@ class SynchronizationProtocol : public Protocol
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
virtual void update() {}
virtual void asynchronousUpdate();
void startCountdown(int ms_countdown);