diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 39b28788..9968f589 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -88,9 +88,12 @@ ServerInterface::ServerInterface() { ServerInterface::~ServerInterface() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - for(int i= 0; i=0 && playerIndexisConnected() == false) { //printf(" yes, its free :)\n"); slots[fromPlayerIndex]->setPlayerIndex(toPlayerIndex); @@ -160,10 +169,17 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){ PlayerIndexMessage playerIndexMessage(toPlayerIndex); slots[toPlayerIndex]->sendMessage(&playerIndexMessage); + + safeMutexSlot.ReleaseLock(); + safeMutexSlot2.ReleaseLock(); + result=true; updateListen(); } else { + safeMutexSlot.ReleaseLock(); + safeMutexSlot2.ReleaseLock(); + safeMutex.ReleaseLock(); } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -173,8 +189,9 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){ void ServerInterface::removeSlot(int playerIndex) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); - MutexSafeWrapper safeMutex(&serverSynchAccessor); + MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); // Mention to everyone that this player is disconnected + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex)); ConnectionSlot *slot = slots[playerIndex]; bool notifyDisconnect = false; @@ -199,6 +216,7 @@ void ServerInterface::removeSlot(int playerIndex) { delete slots[playerIndex]; slots[playerIndex]= NULL; + safeMutexSlot.ReleaseLock(); safeMutex.ReleaseLock(); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); @@ -217,13 +235,15 @@ void ServerInterface::removeSlot(int playerIndex) { } ConnectionSlot* ServerInterface::getSlot(int playerIndex) { + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex)); return slots[playerIndex]; } bool ServerInterface::hasClientConnection() { bool result = false; - for(int i= 0; iisConnected() == true) { result = true; break; @@ -236,7 +256,8 @@ int ServerInterface::getConnectedSlotCount() { int connectedSlotCount= 0; for(int i= 0; itriggerId],intToStr(__LINE__) + "_" + intToStr(event->triggerId)); + if(event->triggerId >= 0 && slots[event->triggerId] == connectionSlot) { if(connectionSlot != NULL && (gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggered == true))) { @@ -464,6 +487,7 @@ bool ServerInterface::signalClientReceiveCommands(ConnectionSlot* connectionSlot void ServerInterface::updateSocketTriggeredList(std::map &socketTriggeredList) { //update all slots for(int i= 0; i < GameConstants::maxPlayers; ++i) { + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); ConnectionSlot* connectionSlot= slots[i]; if(connectionSlot != NULL && connectionSlot->getSocket() != NULL && slots[i]->getSocket()->isSocketValid() == true) { @@ -474,6 +498,7 @@ void ServerInterface::updateSocketTriggeredList(std::map & void ServerInterface::validateConnectedClients() { for(int i= 0; iisConnected() == true) { if(connectionSlot->getPendingNetworkCommandList().size() > 0) { @@ -692,6 +721,7 @@ void ServerInterface::update() { // Step #5 dispatch pending chat messages for(int i= 0; i< GameConstants::maxPlayers; ++i) { + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); ConnectionSlot* connectionSlot= slots[i]; if(connectionSlot != NULL && connectionSlot->getChatTextList().empty() == false) { @@ -913,6 +943,7 @@ void ServerInterface::waitUntilReady(Checksum* checksum) { vector waitingForHosts; allReady= true; for(int i= 0; iisConnected() == true) { if(connectionSlot->isReady() == false) { @@ -979,6 +1010,7 @@ void ServerInterface::waitUntilReady(Checksum* checksum) { try { //send ready message after, so clients start delayed for(int i= 0; i < GameConstants::maxPlayers; ++i) { + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); ConnectionSlot* connectionSlot= slots[i]; if(connectionSlot != NULL && connectionSlot->isConnected() == true) { NetworkMessageReady networkMessageReady(checksum->getSum()); @@ -1037,6 +1069,7 @@ string ServerInterface::getNetworkStatus() { //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); for(int i= 0; igetAllowDownloadDataSynch() == true && @@ -1095,7 +1129,7 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver); - MutexSafeWrapper safeMutex(&masterServerThreadAccessor); + MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__)); delete publishToMasterserverThread; publishToMasterserverThread = NULL; lastMasterserverHeartbeatTime = 0; @@ -1120,7 +1154,7 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings) { void ServerInterface::broadcastGameSetup(const GameSettings* gameSettings) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); - MutexSafeWrapper safeMutex(&serverSynchAccessor); + MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); NetworkMessageLaunch networkMessageLaunch(gameSettings,nmtBroadCastSetup); broadcastMessage(&networkMessageLaunch); @@ -1136,6 +1170,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int // Step #1 signal worker threads to send this broadcast to each client std::map eventList; for(int i= 0; i errorList = connectionSlot->getThreadErrorList(); @@ -1209,6 +1245,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int } else { for(int i= 0; iisConnected() == false) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i); + safeMutexSlot.ReleaseLock(); removeSlot(i); } } @@ -1256,6 +1295,7 @@ void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* n try { for(int i= 0; iisConnected() == false); if(isSlotOpen == true) { @@ -1301,6 +1342,7 @@ int ServerInterface::getOpenSlotCount() { int openSlotCount= 0; for(int i= 0; iisConnected() == false); if(isSlotOpen == true) { @@ -1314,7 +1356,7 @@ int ServerInterface::getOpenSlotCount() { void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount,waitForClientAck); - MutexSafeWrapper safeMutex(&serverSynchAccessor); + MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); gameSettings = *serverGameSettings; @@ -1329,13 +1371,11 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) { gotAckFromAllClients = true; - for(int i= 0; iisConnected()) - { - if(connectionSlot->getReceivedNetworkGameStatus() == false) - { + if(connectionSlot != NULL && connectionSlot->isConnected()) { + if(connectionSlot->getReceivedNetworkGameStatus() == false) { gotAckFromAllClients = false; } @@ -1345,11 +1385,10 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai } } - for(int i= 0; iisConnected()) - { + if(connectionSlot != NULL && connectionSlot->isConnected()) { connectionSlot->setReceivedNetworkGameStatus(false); } } @@ -1357,22 +1396,18 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings()); broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData); - if(waitForClientAck == true) - { + if(waitForClientAck == true) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__); time_t tStart = time(NULL); bool gotAckFromAllClients = false; - while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) - { + while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) { gotAckFromAllClients = true; - for(int i= 0; iisConnected()) - { - if(connectionSlot->getReceivedNetworkGameStatus() == false) - { + if(connectionSlot != NULL && connectionSlot->isConnected()) { + if(connectionSlot->getReceivedNetworkGameStatus() == false) { gotAckFromAllClients = false; } @@ -1435,7 +1470,8 @@ std::map ServerInterface::publishToMasterserver() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); for(int i= 0; i < GameConstants::maxPlayers; ++i) { - if(slots[i] != NULL) { + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); + if(slots[i] != NULL) { slotCountUsed++; slotCountHumans++; ConnectionSlot* connectionSlot= slots[i]; @@ -1478,7 +1514,7 @@ std::map ServerInterface::publishToMasterserver() { void ServerInterface::simpleTask() { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - MutexSafeWrapper safeMutex(&masterServerThreadAccessor); + MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__)); if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= 30) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index 1374a5e2..191bf66e 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -33,6 +33,8 @@ class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbac private: ConnectionSlot* slots[GameConstants::maxPlayers]; + Mutex slotAccessorMutexes[GameConstants::maxPlayers]; + ServerSocket serverSocket; bool gameHasBeenInitiated; int gameSettingsUpdateCount; diff --git a/source/shared_lib/include/platform/sdl/thread.h b/source/shared_lib/include/platform/sdl/thread.h index 892cbb55..8a49fd2c 100644 --- a/source/shared_lib/include/platform/sdl/thread.h +++ b/source/shared_lib/include/platform/sdl/thread.h @@ -3,9 +3,9 @@ // // Copyright (C) 2005 Matthias Braun // -// You can redistribute this code and/or modify it under -// the terms of the GNU General Public License as published -// by the Free Software Foundation; either version 2 of the +// You can redistribute this code and/or modify it under +// the terms of the GNU General Public License as published +// by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== @@ -14,12 +14,17 @@ #include #include +#include #include "leak_dumper.h" +//#define DEBUG_MUTEXES + // ===================================================== // class Thread // ===================================================== +using namespace std; + namespace Shared{ namespace Platform{ class Thread{ @@ -31,17 +36,17 @@ public: pHigh = 3, pRealTime = 4 }; - + private: SDL_Thread* thread; public: Thread(); virtual ~Thread(); - + void start(); virtual void execute()=0; - void setPriority(Thread::Priority threadPriority); + void setPriority(Thread::Priority threadPriority); void suspend(); void resume(); @@ -56,21 +61,25 @@ private: class Mutex { private: SDL_mutex* mutex; + int refCount; public: Mutex(); ~Mutex(); void p(); void v(); + int getRefCount() const { return refCount; } }; class MutexSafeWrapper { protected: Mutex *mutex; + string ownerId; public: - MutexSafeWrapper(Mutex *mutex) { + MutexSafeWrapper(Mutex *mutex,string ownerId="") { this->mutex = mutex; + this->ownerId = ownerId; Lock(); } ~MutexSafeWrapper() { @@ -79,12 +88,37 @@ public: void Lock() { if(this->mutex != NULL) { + #ifdef DEBUG_MUTEXES + if(ownerId != "") { + printf("Locking Mutex [%s] refCount: %d\n",ownerId.c_str(),this->mutex->getRefCount()); + } + #endif + this->mutex->p(); + + #ifdef DEBUG_MUTEXES + if(ownerId != "") { + printf("Locked Mutex [%s] refCount: %d\n",ownerId.c_str(),this->mutex->getRefCount()); + } + #endif } } void ReleaseLock(bool keepMutex=false) { if(this->mutex != NULL) { + #ifdef DEBUG_MUTEXES + if(ownerId != "") { + printf("UnLocking Mutex [%s] refCount: %d\n",ownerId.c_str(),this->mutex->getRefCount()); + } + #endif + this->mutex->v(); + + #ifdef DEBUG_MUTEXES + if(ownerId != "") { + printf("UnLocked Mutex [%s] refCount: %d\n",ownerId.c_str(),this->mutex->getRefCount()); + } + #endif + if(keepMutex == false) { this->mutex = NULL; } diff --git a/source/shared_lib/sources/platform/sdl/thread.cpp b/source/shared_lib/sources/platform/sdl/thread.cpp index a2239c31..80396a58 100644 --- a/source/shared_lib/sources/platform/sdl/thread.cpp +++ b/source/shared_lib/sources/platform/sdl/thread.cpp @@ -1,9 +1,9 @@ //This file is part of Glest Shared Library (www.glest.org) //Copyright (C) 2005 Matthias Braun -//You can redistribute this code and/or modify it under -//the terms of the GNU General Public License as published by the Free Software -//Foundation; either version 2 of the License, or (at your option) any later +//You can redistribute this code and/or modify it under +//the terms of the GNU General Public License as published by the Free Software +//Foundation; either version 2 of the License, or (at your option) any later //version. #include "thread.h" @@ -23,10 +23,10 @@ using namespace std; #endif -namespace Shared{ namespace Platform{ +namespace Shared{ namespace Platform{ // ===================================== -// Threads +// Threads // ===================================== Thread::Thread() { thread = NULL; @@ -74,10 +74,11 @@ void Thread::resume() { } // ===================================== -// Mutex +// Mutex // ===================================== Mutex::Mutex() { + refCount=0; mutex = SDL_CreateMutex(); assert(mutex != NULL); if(mutex == NULL) { @@ -104,6 +105,7 @@ void Mutex::p() { throw runtime_error(szBuf); } SDL_mutexP(mutex); + refCount++; } void Mutex::v() { @@ -112,6 +114,7 @@ void Mutex::v() { snprintf(szBuf,1023,"In [%s::%s Line: %d] mutex == NULL",__FILE__,__FUNCTION__,__LINE__); throw runtime_error(szBuf); } + refCount--; SDL_mutexV(mutex); }