- another attempt to guard socket thread access so avoid menu hang problems

This commit is contained in:
Mark Vejvoda 2010-12-18 19:52:47 +00:00
parent 7305391b6d
commit 6a99e2db8e
4 changed files with 125 additions and 50 deletions

View File

@ -88,9 +88,12 @@ ServerInterface::ServerInterface() {
ServerInterface::~ServerInterface() { ServerInterface::~ServerInterface() {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){ for(int i= 0; i<GameConstants::maxPlayers; ++i) {
delete slots[i]; if(slots[i] != NULL) {
slots[i]=NULL; MutexSafeWrapper safeMutex(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i) + "_" + intToStr(i));
delete slots[i];
slots[i]=NULL;
}
delete switchSetupRequests[i]; delete switchSetupRequests[i];
switchSetupRequests[i]=NULL; switchSetupRequests[i]=NULL;
@ -100,7 +103,7 @@ ServerInterface::~ServerInterface() {
close(); close();
MutexSafeWrapper safeMutex(&masterServerThreadAccessor); MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__));
delete publishToMasterserverThread; delete publishToMasterserverThread;
publishToMasterserverThread = NULL; publishToMasterserverThread = NULL;
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@ -119,17 +122,19 @@ void ServerInterface::addSlot(int playerIndex){
assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers); assert(playerIndex>=0 && playerIndex<GameConstants::maxPlayers);
MutexSafeWrapper safeMutex(&serverSynchAccessor); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
if(serverSocket.isPortBound() == false) { if(serverSocket.isPortBound() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
serverSocket.bind(serverSocket.getBindPort()); serverSocket.bind(serverSocket.getBindPort());
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete slots[playerIndex];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex));
delete slots[playerIndex];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
slots[playerIndex]= new ConnectionSlot(this, playerIndex); slots[playerIndex]= new ConnectionSlot(this, playerIndex);
safeMutexSlot.ReleaseLock();
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@ -148,7 +153,11 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){
if(fromPlayerIndex==toPlayerIndex) return false;// doubleclicked or whatever if(fromPlayerIndex==toPlayerIndex) return false;// doubleclicked or whatever
//printf(" checking if slot %d is free?\n",toPlayerIndex); //printf(" checking if slot %d is free?\n",toPlayerIndex);
MutexSafeWrapper safeMutex(&serverSynchAccessor); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[fromPlayerIndex],intToStr(__LINE__) + "_" + intToStr(fromPlayerIndex));
MutexSafeWrapper safeMutexSlot2(&slotAccessorMutexes[toPlayerIndex],intToStr(__LINE__) + "_" + intToStr(toPlayerIndex));
if( slots[toPlayerIndex]->isConnected() == false) { if( slots[toPlayerIndex]->isConnected() == false) {
//printf(" yes, its free :)\n"); //printf(" yes, its free :)\n");
slots[fromPlayerIndex]->setPlayerIndex(toPlayerIndex); slots[fromPlayerIndex]->setPlayerIndex(toPlayerIndex);
@ -160,10 +169,17 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex){
PlayerIndexMessage playerIndexMessage(toPlayerIndex); PlayerIndexMessage playerIndexMessage(toPlayerIndex);
slots[toPlayerIndex]->sendMessage(&playerIndexMessage); slots[toPlayerIndex]->sendMessage(&playerIndexMessage);
safeMutexSlot.ReleaseLock();
safeMutexSlot2.ReleaseLock();
result=true; result=true;
updateListen(); updateListen();
} }
else { else {
safeMutexSlot.ReleaseLock();
safeMutexSlot2.ReleaseLock();
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
} }
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); 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) { void ServerInterface::removeSlot(int playerIndex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,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 // Mention to everyone that this player is disconnected
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex));
ConnectionSlot *slot = slots[playerIndex]; ConnectionSlot *slot = slots[playerIndex];
bool notifyDisconnect = false; bool notifyDisconnect = false;
@ -199,6 +216,7 @@ void ServerInterface::removeSlot(int playerIndex) {
delete slots[playerIndex]; delete slots[playerIndex];
slots[playerIndex]= NULL; slots[playerIndex]= NULL;
safeMutexSlot.ReleaseLock();
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); 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) { ConnectionSlot* ServerInterface::getSlot(int playerIndex) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex));
return slots[playerIndex]; return slots[playerIndex];
} }
bool ServerInterface::hasClientConnection() { bool ServerInterface::hasClientConnection() {
bool result = false; bool result = false;
for(int i= 0; i<GameConstants::maxPlayers; ++i){ for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
if(slots[i] != NULL && slots[i]->isConnected() == true) { if(slots[i] != NULL && slots[i]->isConnected() == true) {
result = true; result = true;
break; break;
@ -236,7 +256,8 @@ int ServerInterface::getConnectedSlotCount() {
int connectedSlotCount= 0; int connectedSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
if(slots[i]!= NULL){ MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
if(slots[i] != NULL) {
++connectedSlotCount; ++connectedSlotCount;
} }
} }
@ -275,6 +296,8 @@ void ServerInterface::updateSlot(ConnectionSlotEvent *event) {
bool checkForNewClients = true; bool checkForNewClients = true;
// Safety check since we can experience a disconnect and the slot is NULL // Safety check since we can experience a disconnect and the slot is NULL
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[event->triggerId],intToStr(__LINE__) + "_" + intToStr(event->triggerId));
if(event->triggerId >= 0 && slots[event->triggerId] == connectionSlot) { if(event->triggerId >= 0 && slots[event->triggerId] == connectionSlot) {
if(connectionSlot != NULL && if(connectionSlot != NULL &&
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggered == true))) { (gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggered == true))) {
@ -464,6 +487,7 @@ bool ServerInterface::signalClientReceiveCommands(ConnectionSlot* connectionSlot
void ServerInterface::updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList) { void ServerInterface::updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList) {
//update all slots //update all slots
for(int i= 0; i < GameConstants::maxPlayers; ++i) { for(int i= 0; i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL && if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
slots[i]->getSocket()->isSocketValid() == true) { slots[i]->getSocket()->isSocketValid() == true) {
@ -474,6 +498,7 @@ void ServerInterface::updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &
void ServerInterface::validateConnectedClients() { void ServerInterface::validateConnectedClients() {
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Slot # %d\n",__FILE__,__FUNCTION__,__LINE__,i); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Slot # %d\n",__FILE__,__FUNCTION__,__LINE__,i);
@ -509,6 +534,7 @@ void ServerInterface::update() {
// Step #1 tell all connection slot worker threads to receive socket data // Step #1 tell all connection slot worker threads to receive socket data
bool checkForNewClients = true; bool checkForNewClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
@ -529,6 +555,7 @@ void ServerInterface::update() {
threadsDone = true; threadsDone = true;
// Examine all threads for completion of delegation // Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && mapSlotSignalledList[i] == true && if(connectionSlot != NULL && mapSlotSignalledList[i] == true &&
slotsCompleted.find(i) == slotsCompleted.end()) { slotsCompleted.find(i) == slotsCompleted.end()) {
@ -582,6 +609,7 @@ void ServerInterface::update() {
threadsDone = true; threadsDone = true;
// Examine all threads for completion of delegation // Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && mapSlotSignalledList[i] == true && if(connectionSlot != NULL && mapSlotSignalledList[i] == true &&
slotsCompleted.find(i) == slotsCompleted.end()) { slotsCompleted.find(i) == slotsCompleted.end()) {
@ -667,6 +695,7 @@ void ServerInterface::update() {
// Step #4 dispatch network commands to the pending list so that they are done in proper order // Step #4 dispatch network commands to the pending list so that they are done in proper order
if(gameHasBeenInitiated == true) { if(gameHasBeenInitiated == true) {
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true) { if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
if(connectionSlot->getPendingNetworkCommandList().size() > 0) { if(connectionSlot->getPendingNetworkCommandList().size() > 0) {
@ -692,6 +721,7 @@ void ServerInterface::update() {
// Step #5 dispatch pending chat messages // Step #5 dispatch pending chat messages
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && if(connectionSlot != NULL &&
connectionSlot->getChatTextList().empty() == false) { connectionSlot->getChatTextList().empty() == false) {
@ -913,6 +943,7 @@ void ServerInterface::waitUntilReady(Checksum* checksum) {
vector<string> waitingForHosts; vector<string> waitingForHosts;
allReady= true; allReady= true;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true) { if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
if(connectionSlot->isReady() == false) { if(connectionSlot->isReady() == false) {
@ -979,6 +1010,7 @@ void ServerInterface::waitUntilReady(Checksum* checksum) {
try { try {
//send ready message after, so clients start delayed //send ready message after, so clients start delayed
for(int i= 0; i < GameConstants::maxPlayers; ++i) { for(int i= 0; i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true) { if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
NetworkMessageReady networkMessageReady(checksum->getSum()); NetworkMessageReady networkMessageReady(checksum->getSum());
@ -1037,6 +1069,7 @@ string ServerInterface::getNetworkStatus() {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i<GameConstants::maxPlayers; ++i){ for(int i= 0; i<GameConstants::maxPlayers; ++i){
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
str+= intToStr(i)+ ": "; str+= intToStr(i)+ ": ";
@ -1072,6 +1105,7 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot *connectionSlot= slots[i]; ConnectionSlot *connectionSlot= slots[i];
if(connectionSlot != NULL && if(connectionSlot != NULL &&
connectionSlot->getAllowDownloadDataSynch() == true && connectionSlot->getAllowDownloadDataSynch() == 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); 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; delete publishToMasterserverThread;
publishToMasterserverThread = NULL; publishToMasterserverThread = NULL;
lastMasterserverHeartbeatTime = 0; lastMasterserverHeartbeatTime = 0;
@ -1120,7 +1154,7 @@ bool ServerInterface::launchGame(const GameSettings* gameSettings) {
void ServerInterface::broadcastGameSetup(const GameSettings* gameSettings) { void ServerInterface::broadcastGameSetup(const GameSettings* gameSettings) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); 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); NetworkMessageLaunch networkMessageLaunch(gameSettings,nmtBroadCastSetup);
broadcastMessage(&networkMessageLaunch); 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 // Step #1 signal worker threads to send this broadcast to each client
std::map<int,ConnectionSlotEvent> eventList; std::map<int,ConnectionSlotEvent> eventList;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
// New lag check // New lag check
@ -1184,6 +1219,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
threadsDone = true; threadsDone = true;
// Examine all threads for completion of delegation // Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) { for(int i= 0; i< GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot = slots[i]; ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && slotsCompleted.find(i) == slotsCompleted.end()) { if(connectionSlot != NULL && slotsCompleted.find(i) == slotsCompleted.end()) {
std::vector<std::string> errorList = connectionSlot->getThreadErrorList(); std::vector<std::string> errorList = connectionSlot->getThreadErrorList();
@ -1209,6 +1245,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
} }
else { else {
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(i != excludeSlot && connectionSlot != NULL) { if(i != excludeSlot && connectionSlot != NULL) {
@ -1226,6 +1263,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
else if(gameHasBeenInitiated == true) { else if(gameHasBeenInitiated == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,__LINE__,i);
safeMutexSlot.ReleaseLock();
removeSlot(i); removeSlot(i);
} }
//} //}
@ -1233,6 +1271,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
else if(i == excludeSlot && gameHasBeenInitiated == true && else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false) { connectionSlot != NULL && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
safeMutexSlot.ReleaseLock();
removeSlot(i); removeSlot(i);
} }
} }
@ -1256,6 +1295,7 @@ void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* n
try { try {
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
if(i!= excludeSlot && connectionSlot!= NULL) { if(i!= excludeSlot && connectionSlot!= NULL) {
@ -1282,9 +1322,10 @@ void ServerInterface::updateListen() {
return; return;
} }
MutexSafeWrapper safeMutex(&serverSynchAccessor); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__));
int openSlotCount= 0; int openSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
bool isSlotOpen = (slots[i] != NULL && slots[i]->isConnected() == false); bool isSlotOpen = (slots[i] != NULL && slots[i]->isConnected() == false);
if(isSlotOpen == true) { if(isSlotOpen == true) {
@ -1301,6 +1342,7 @@ int ServerInterface::getOpenSlotCount() {
int openSlotCount= 0; int openSlotCount= 0;
for(int i= 0; i<GameConstants::maxPlayers; ++i) { for(int i= 0; i<GameConstants::maxPlayers; ++i) {
//MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
bool isSlotOpen = (slots[i] != NULL && slots[i]->isConnected() == false); bool isSlotOpen = (slots[i] != NULL && slots[i]->isConnected() == false);
if(isSlotOpen == true) { if(isSlotOpen == true) {
@ -1314,7 +1356,7 @@ int ServerInterface::getOpenSlotCount() {
void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) { void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount,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; gameSettings = *serverGameSettings;
@ -1329,13 +1371,11 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5)
{ {
gotAckFromAllClients = true; gotAckFromAllClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i) for(int i= 0; i<GameConstants::maxPlayers; ++i) {
{ MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot *connectionSlot = slots[i]; ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected()) if(connectionSlot != NULL && connectionSlot->isConnected()) {
{ if(connectionSlot->getReceivedNetworkGameStatus() == false) {
if(connectionSlot->getReceivedNetworkGameStatus() == false)
{
gotAckFromAllClients = false; gotAckFromAllClients = false;
} }
@ -1345,11 +1385,10 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai
} }
} }
for(int i= 0; i<GameConstants::maxPlayers; ++i) for(int i= 0; i<GameConstants::maxPlayers; ++i) {
{ MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot *connectionSlot = slots[i]; ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected()) if(connectionSlot != NULL && connectionSlot->isConnected()) {
{
connectionSlot->setReceivedNetworkGameStatus(false); connectionSlot->setReceivedNetworkGameStatus(false);
} }
} }
@ -1357,22 +1396,18 @@ void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool wai
NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings()); NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData(getGameSettings());
broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData); broadcastMessageToConnectedClients(&networkMessageSynchNetworkGameData);
if(waitForClientAck == true) if(waitForClientAck == true) {
{
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Waiting for client acks #2\n",__FILE__,__FUNCTION__);
time_t tStart = time(NULL); time_t tStart = time(NULL);
bool gotAckFromAllClients = false; bool gotAckFromAllClients = false;
while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) while(gotAckFromAllClients == false && difftime(time(NULL),tStart) <= 5) {
{
gotAckFromAllClients = true; gotAckFromAllClients = true;
for(int i= 0; i<GameConstants::maxPlayers; ++i) for(int i= 0; i<GameConstants::maxPlayers; ++i) {
{ MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i));
ConnectionSlot *connectionSlot = slots[i]; ConnectionSlot *connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected()) if(connectionSlot != NULL && connectionSlot->isConnected()) {
{ if(connectionSlot->getReceivedNetworkGameStatus() == false) {
if(connectionSlot->getReceivedNetworkGameStatus() == false)
{
gotAckFromAllClients = false; gotAckFromAllClients = false;
} }
@ -1435,7 +1470,8 @@ std::map<string,string> ServerInterface::publishToMasterserver() {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(int i= 0; i < GameConstants::maxPlayers; ++i) { 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++; slotCountUsed++;
slotCountHumans++; slotCountHumans++;
ConnectionSlot* connectionSlot= slots[i]; ConnectionSlot* connectionSlot= slots[i];
@ -1478,7 +1514,7 @@ std::map<string,string> ServerInterface::publishToMasterserver() {
void ServerInterface::simpleTask() { void ServerInterface::simpleTask() {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); //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) { if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= 30) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);

View File

@ -33,6 +33,8 @@ class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbac
private: private:
ConnectionSlot* slots[GameConstants::maxPlayers]; ConnectionSlot* slots[GameConstants::maxPlayers];
Mutex slotAccessorMutexes[GameConstants::maxPlayers];
ServerSocket serverSocket; ServerSocket serverSocket;
bool gameHasBeenInitiated; bool gameHasBeenInitiated;
int gameSettingsUpdateCount; int gameSettingsUpdateCount;

View File

@ -3,9 +3,9 @@
// //
// Copyright (C) 2005 Matthias Braun <matze@braunis.de> // Copyright (C) 2005 Matthias Braun <matze@braunis.de>
// //
// You can redistribute this code and/or modify it under // You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published // the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the // by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version // License, or (at your option) any later version
// ============================================================== // ==============================================================
@ -14,12 +14,17 @@
#include <SDL_thread.h> #include <SDL_thread.h>
#include <SDL_mutex.h> #include <SDL_mutex.h>
#include <string>
#include "leak_dumper.h" #include "leak_dumper.h"
//#define DEBUG_MUTEXES
// ===================================================== // =====================================================
// class Thread // class Thread
// ===================================================== // =====================================================
using namespace std;
namespace Shared{ namespace Platform{ namespace Shared{ namespace Platform{
class Thread{ class Thread{
@ -31,17 +36,17 @@ public:
pHigh = 3, pHigh = 3,
pRealTime = 4 pRealTime = 4
}; };
private: private:
SDL_Thread* thread; SDL_Thread* thread;
public: public:
Thread(); Thread();
virtual ~Thread(); virtual ~Thread();
void start(); void start();
virtual void execute()=0; virtual void execute()=0;
void setPriority(Thread::Priority threadPriority); void setPriority(Thread::Priority threadPriority);
void suspend(); void suspend();
void resume(); void resume();
@ -56,21 +61,25 @@ private:
class Mutex { class Mutex {
private: private:
SDL_mutex* mutex; SDL_mutex* mutex;
int refCount;
public: public:
Mutex(); Mutex();
~Mutex(); ~Mutex();
void p(); void p();
void v(); void v();
int getRefCount() const { return refCount; }
}; };
class MutexSafeWrapper { class MutexSafeWrapper {
protected: protected:
Mutex *mutex; Mutex *mutex;
string ownerId;
public: public:
MutexSafeWrapper(Mutex *mutex) { MutexSafeWrapper(Mutex *mutex,string ownerId="") {
this->mutex = mutex; this->mutex = mutex;
this->ownerId = ownerId;
Lock(); Lock();
} }
~MutexSafeWrapper() { ~MutexSafeWrapper() {
@ -79,12 +88,37 @@ public:
void Lock() { void Lock() {
if(this->mutex != NULL) { 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(); 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) { void ReleaseLock(bool keepMutex=false) {
if(this->mutex != NULL) { 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(); 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) { if(keepMutex == false) {
this->mutex = NULL; this->mutex = NULL;
} }

View File

@ -1,9 +1,9 @@
//This file is part of Glest Shared Library (www.glest.org) //This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de> //Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code and/or modify it under //You can redistribute this code and/or modify it under
//the terms of the GNU General Public License as published by the Free Software //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 //Foundation; either version 2 of the License, or (at your option) any later
//version. //version.
#include "thread.h" #include "thread.h"
@ -23,10 +23,10 @@ using namespace std;
#endif #endif
namespace Shared{ namespace Platform{ namespace Shared{ namespace Platform{
// ===================================== // =====================================
// Threads // Threads
// ===================================== // =====================================
Thread::Thread() { Thread::Thread() {
thread = NULL; thread = NULL;
@ -74,10 +74,11 @@ void Thread::resume() {
} }
// ===================================== // =====================================
// Mutex // Mutex
// ===================================== // =====================================
Mutex::Mutex() { Mutex::Mutex() {
refCount=0;
mutex = SDL_CreateMutex(); mutex = SDL_CreateMutex();
assert(mutex != NULL); assert(mutex != NULL);
if(mutex == NULL) { if(mutex == NULL) {
@ -104,6 +105,7 @@ void Mutex::p() {
throw runtime_error(szBuf); throw runtime_error(szBuf);
} }
SDL_mutexP(mutex); SDL_mutexP(mutex);
refCount++;
} }
void Mutex::v() { void Mutex::v() {
@ -112,6 +114,7 @@ void Mutex::v() {
snprintf(szBuf,1023,"In [%s::%s Line: %d] mutex == NULL",__FILE__,__FUNCTION__,__LINE__); snprintf(szBuf,1023,"In [%s::%s Line: %d] mutex == NULL",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(szBuf); throw runtime_error(szBuf);
} }
refCount--;
SDL_mutexV(mutex); SDL_mutexV(mutex);
} }