- attempt to fix network stuttering using a new multi-read single write mutex + semaphore class

This commit is contained in:
Mark Vejvoda
2011-11-26 08:14:23 +00:00
parent b8d71ffb0d
commit 6c1c248d62
8 changed files with 390 additions and 85 deletions

View File

@@ -32,16 +32,18 @@ namespace Glest{ namespace Game{
// class ConnectionSlotThread // class ConnectionSlotThread
// ===================================================== // =====================================================
ConnectionSlotThread::ConnectionSlotThread(int slotIndex) : BaseThread() { ConnectionSlotThread::ConnectionSlotThread(ConnectionSlot *slot) : BaseThread() {
this->slotIndex = slotIndex; this->slot = slot;
this->slotIndex = slot->getPlayerIndex();
this->slotInterface = NULL; this->slotInterface = NULL;
//this->event = NULL; //this->event = NULL;
eventList.clear(); eventList.clear();
eventList.reserve(100); eventList.reserve(100);
} }
ConnectionSlotThread::ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,int slotIndex) : BaseThread() { ConnectionSlotThread::ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,ConnectionSlot *slot) : BaseThread() {
this->slotIndex = slotIndex; this->slot = slot;
this->slotIndex = slot->getPlayerIndex();
this->slotInterface = slotInterface; this->slotInterface = slotInterface;
//this->event = NULL; //this->event = NULL;
eventList.clear(); eventList.clear();
@@ -203,10 +205,12 @@ void ConnectionSlotThread::execute() {
//this->slotInterface->slotUpdateTask(&eventCopy); //this->slotInterface->slotUpdateTask(&eventCopy);
this->slotUpdateTask(&eventCopy); this->slotUpdateTask(&eventCopy);
setTaskCompleted(eventCopy.eventId); setTaskCompleted(eventCopy.eventId);
this->slot->signalSlotWorkerTaskCompleted();
} }
} }
else { else {
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
this->slot->signalSlotWorkerTaskCompleted();
} }
if(getQuitStatus() == true) { if(getQuitStatus() == true) {
@@ -219,12 +223,14 @@ void ConnectionSlotThread::execute() {
} }
catch(const exception &ex) { catch(const exception &ex) {
//setRunningStatus(false); //setRunningStatus(false);
this->slot->signalSlotWorkerTaskCompleted();
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(ex.what()); throw runtime_error(ex.what());
} }
this->slot->signalSlotWorkerTaskCompleted();
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
} }
@@ -250,7 +256,7 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex
this->setSocket(NULL); this->setSocket(NULL);
this->slotThreadWorker = NULL; this->slotThreadWorker = NULL;
this->slotThreadWorker = new ConnectionSlotThread(this->serverInterface,playerIndex); this->slotThreadWorker = new ConnectionSlotThread(this->serverInterface,this);
this->slotThreadWorker->setUniqueID(__FILE__); this->slotThreadWorker->setUniqueID(__FILE__);
this->slotThreadWorker->start(); this->slotThreadWorker->start();
@@ -286,6 +292,15 @@ ConnectionSlot::~ConnectionSlot() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__);
} }
void ConnectionSlot::signalSlotWorkerTaskCompleted() {
semSlotWorkerTaskCompleted.signal();
}
bool ConnectionSlot::waitSlotWorkerTaskCompleted(int waitMilliseconds) {
int result = semSlotWorkerTaskCompleted.waitTillSignalled(waitMilliseconds);
return (result == 0);
}
void ConnectionSlot::updateSlot(ConnectionSlotEvent *event) { void ConnectionSlot::updateSlot(ConnectionSlotEvent *event) {
Chrono chrono; Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
@@ -546,11 +561,13 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
lastReceiveCommandListTime = time(NULL); lastReceiveCommandListTime = time(NULL);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount);
MutexSafeWrapper safeMutexSlot(&mutexPendingNetworkCommandList,CODE_AT_LINE); if(networkMessageCommandList.getCommandCount() > 0) {
for(int i = 0; i < networkMessageCommandList.getCommandCount(); ++i) { MutexSafeWrapper safeMutexSlot(&mutexPendingNetworkCommandList,CODE_AT_LINE);
vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i)); for(int i = 0; i < networkMessageCommandList.getCommandCount(); ++i) {
vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i));
}
safeMutexSlot.ReleaseLock();
} }
safeMutexSlot.ReleaseLock();
} }
else { else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str()); if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
@@ -1067,7 +1084,7 @@ bool ConnectionSlot::updateCompleted(ConnectionSlotEvent *event) {
} }
void ConnectionSlot::sendMessage(const NetworkMessage* networkMessage) { void ConnectionSlot::sendMessage(const NetworkMessage* networkMessage) {
MutexSafeWrapper safeMutex(&socketSynchAccessor,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&socketSynchAccessor,CODE_AT_LINE);
// Skip text messages not intended for the players preferred language // Skip text messages not intended for the players preferred language
const NetworkMessageText *textMsg = dynamic_cast<const NetworkMessageText *>(networkMessage); const NetworkMessageText *textMsg = dynamic_cast<const NetworkMessageText *>(networkMessage);
@@ -1109,72 +1126,90 @@ void ConnectionSlot::clearPendingNetworkCommandList() {
safeMutexSlot.ReleaseLock(); safeMutexSlot.ReleaseLock();
} }
bool ConnectionSlot::hasValidSocketId() { //bool ConnectionSlot::hasValidSocketId() {
//bool result = (this->getSocket() != NULL && this->getSocket()->getSocketId() > 0); // //bool result = (this->getSocket() != NULL && this->getSocket()->getSocketId() > 0);
//return result; // //return result;
bool result = false; // bool result = false;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); // MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
if(socket != NULL && socket->getSocketId() > 0) { // if(socket != NULL && socket->getSocketId() > 0) {
result = true; // result = true;
} // }
return result; // return result;
//
} //}
bool ConnectionSlot::isConnected() { bool ConnectionSlot::isConnected() {
bool result = false; bool result = false;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,true,CODE_AT_LINE);
if(socket != NULL && socket->isConnected() == true) { if(socket != NULL && socket->isConnected() == true) {
result = true; result = true;
} }
//socketRWLMutex.unlockRead();
return result; return result;
} }
PLATFORM_SOCKET ConnectionSlot::getSocketId() { PLATFORM_SOCKET ConnectionSlot::getSocketId() {
PLATFORM_SOCKET result = 0; PLATFORM_SOCKET result = 0;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,true,CODE_AT_LINE);
if(socket != NULL) { if(socket != NULL) {
result = socket->getSocketId(); result = socket->getSocketId();
} }
//socketRWLMutex.unlockRead();
return result; return result;
} }
pair<bool,Socket*> ConnectionSlot::getSocketInfo() { pair<bool,Socket*> ConnectionSlot::getSocketInfo() {
pair<bool,Socket*> result; pair<bool,Socket*> result;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,true,CODE_AT_LINE);
result.first = (socket != NULL && socket->isConnected()); result.first = (socket != NULL && socket->isConnected());
result.second = socket; result.second = socket;
//socketRWLMutex.unlockRead();
return result; return result;
} }
Socket* ConnectionSlot::getSocket(bool mutexLock) { Socket* ConnectionSlot::getSocket(bool mutexLock) {
MutexSafeWrapper safeMutexSlot(NULL,CODE_AT_LINE); Socket *result = NULL;
//MutexSafeWrapper safeMutexSlot(NULL,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,true,CODE_AT_LINE);
if(mutexLock == true) { if(mutexLock == true) {
safeMutexSlot.setMutex(&mutexSocket,CODE_AT_LINE); //safeMutexSlot.setMutex(&mutexSocket,CODE_AT_LINE);
} }
return socket; result = socket;
//socketRWLMutex.unlockRead();
return result;
} }
void ConnectionSlot::setSocket(Socket *newSocket) { void ConnectionSlot::setSocket(Socket *newSocket) {
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,false,CODE_AT_LINE);
socket = newSocket; socket = newSocket;
//socketRWLMutex.unlockWrite();
} }
void ConnectionSlot::deleteSocket() { void ConnectionSlot::deleteSocket() {
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,false,CODE_AT_LINE);
delete socket; delete socket;
socket = NULL; socket = NULL;
//socketRWLMutex.unlockWrite();
} }
bool ConnectionSlot::hasDataToRead() { bool ConnectionSlot::hasDataToRead() {
bool result = false; bool result = false;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE); //MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeRWL(&socketRWLMutex,true,CODE_AT_LINE);
if(socket != NULL && socket->hasDataToRead() == true) { if(socket != NULL && socket->hasDataToRead() == true) {
result = true; result = true;
} }
//socketRWLMutex.unlockRead();
return result; return result;
} }

View File

@@ -78,6 +78,7 @@ protected:
Mutex triggerIdMutex; Mutex triggerIdMutex;
vector<ConnectionSlotEvent> eventList; vector<ConnectionSlotEvent> eventList;
int slotIndex; int slotIndex;
ConnectionSlot *slot;
virtual void setQuitStatus(bool value); virtual void setQuitStatus(bool value);
virtual void setTaskCompleted(int eventId); virtual void setTaskCompleted(int eventId);
@@ -86,8 +87,8 @@ protected:
void slotUpdateTask(ConnectionSlotEvent *event); void slotUpdateTask(ConnectionSlotEvent *event);
public: public:
ConnectionSlotThread(int slotIndex); ConnectionSlotThread(ConnectionSlot *slot);
ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,int slotIndex); ConnectionSlotThread(ConnectionSlotCallbackInterface *slotInterface,ConnectionSlot *slot);
virtual void execute(); virtual void execute();
void signalUpdate(ConnectionSlotEvent *event); void signalUpdate(ConnectionSlotEvent *event);
bool isSignalCompleted(ConnectionSlotEvent *event); bool isSignalCompleted(ConnectionSlotEvent *event);
@@ -106,7 +107,9 @@ class ConnectionSlot: public NetworkInterface {
private: private:
ServerInterface* serverInterface; ServerInterface* serverInterface;
Mutex mutexSocket; Semaphore semSlotWorkerTaskCompleted;
//Mutex mutexSocket;
Socket* socket; Socket* socket;
int playerIndex; int playerIndex;
string name; string name;
@@ -131,10 +134,15 @@ private:
int playerStatus; int playerStatus;
string playerLanguage; string playerLanguage;
ReadWriteMutex socketRWLMutex;
public: public:
ConnectionSlot(ServerInterface* serverInterface, int playerIndex); ConnectionSlot(ServerInterface* serverInterface, int playerIndex);
~ConnectionSlot(); ~ConnectionSlot();
void signalSlotWorkerTaskCompleted();
bool waitSlotWorkerTaskCompleted(int waitMilliseconds=-1);
void update(bool checkForNewClients,int lockedSlotIndex); void update(bool checkForNewClients,int lockedSlotIndex);
void setPlayerIndex(int value) { playerIndex = value; } void setPlayerIndex(int value) { playerIndex = value; }
int getPlayerIndex() const {return playerIndex;} int getPlayerIndex() const {return playerIndex;}
@@ -155,7 +163,7 @@ public:
bool getReceivedNetworkGameStatus() const { return receivedNetworkGameStatus; } bool getReceivedNetworkGameStatus() const { return receivedNetworkGameStatus; }
void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; } void setReceivedNetworkGameStatus(bool value) { receivedNetworkGameStatus = value; }
bool hasValidSocketId(); //bool hasValidSocketId();
virtual bool getConnectHasHandshaked() const { return gotIntro; } virtual bool getConnectHasHandshaked() const { return gotIntro; }
std::vector<std::string> getThreadErrorList() const { return threadErrorList; } std::vector<std::string> getThreadErrorList() const { return threadErrorList; }
void clearThreadErrorList() { threadErrorList.clear(); } void clearThreadErrorList() { threadErrorList.clear(); }

View File

@@ -882,6 +882,53 @@ void ServerInterface::checkForLaggingClients(std::map<int,bool> &mapSlotSignalle
} }
} }
void ServerInterface::checkForLaggingClients(std::vector <string> &errorMsgList) {
bool lastGlobalLagCheckTimeUpdate = false;
time_t waitForClientsElapsed = time(NULL);
time_t waitForThreadElapsed = time(NULL);
std::map<int,bool> slotsWarnedList;
// Examine all threads for completion of delegation
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],CODE_AT_LINE_X(i));
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true) {
try {
if(gameHasBeenInitiated == true &&
difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) {
//printf("\n\n\n^^^^^^^^^^^^^^ PART A\n\n\n");
// New lag check
std::pair<bool,bool> clientLagExceededOrWarned = std::make_pair(false,false);
if( gameHasBeenInitiated == true && connectionSlot != NULL &&
connectionSlot->isConnected() == true) {
//printf("\n\n\n^^^^^^^^^^^^^^ PART B\n\n\n");
lastGlobalLagCheckTimeUpdate = true;
clientLagExceededOrWarned = clientLagCheck(connectionSlot,slotsWarnedList[i]);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, gameSettings.getNetworkPauseGameForLaggedClients() = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second,gameSettings.getNetworkPauseGameForLaggedClients());
if(clientLagExceededOrWarned.first == true) {
slotsWarnedList[i] = true;
}
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
errorMsgList.push_back(ex.what());
}
}
}
if(lastGlobalLagCheckTimeUpdate == true) {
lastGlobalLagCheckTime = time(NULL);
}
}
void ServerInterface::executeNetworkCommandsFromClients() { void ServerInterface::executeNetworkCommandsFromClients() {
if(gameHasBeenInitiated == true) { if(gameHasBeenInitiated == true) {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
@@ -948,6 +995,36 @@ void ServerInterface::dispatchPendingChatMessages(std::vector <string> &errorMsg
} }
} }
void ServerInterface::waitForSignalledClients(std::map<int,bool> &mapSlotSignalledList,std::vector <string> &errorMsgList) {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
if(mapSlotSignalledList[i] == true) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],CODE_AT_LINE_X(i));
ConnectionSlot* connectionSlot= slots[i];
safeMutexSlot.ReleaseLock(true);
if(connectionSlot != NULL) {
connectionSlot->waitSlotWorkerTaskCompleted(4000);
safeMutexSlot.Lock();
connectionSlot= slots[i];
if(connectionSlot != NULL) {
std::vector<std::string> errorList = connectionSlot->getThreadErrorList();
// Collect any collected errors from threads
if(errorList.empty() == false) {
for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) {
string &sErr = errorList[iErrIdx];
if(sErr != "") {
errorMsgList.push_back(sErr);
}
}
connectionSlot->clearThreadErrorList();
}
}
safeMutexSlot.ReleaseLock();
}
}
}
}
void ServerInterface::update() { void ServerInterface::update() {
Chrono chrono; Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
@@ -998,14 +1075,18 @@ void ServerInterface::update() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
waitForSignalledClients(mapSlotSignalledList,errorMsgList);
/*
// Step #2 check all connection slot worker threads for completed status // Step #2 check all connection slot worker threads for completed status
checkForCompletedClients(mapSlotSignalledList,errorMsgList, eventList); checkForCompletedClients(mapSlotSignalledList,errorMsgList, eventList);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
*/
// Step #3 check clients for any lagging scenarios and try to deal with them // Step #3 check clients for any lagging scenarios and try to deal with them
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList); //checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
checkForLaggingClients(errorMsgList);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #4\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #4\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
@@ -1027,9 +1108,9 @@ void ServerInterface::update() {
//printf("\nServerInterface::update -- E1\n"); //printf("\nServerInterface::update -- E1\n");
//std::map<int,ConnectionSlotEvent> eventList; //std::map<int,ConnectionSlotEvent> eventList;
std::map<int,bool> mapSlotSignalledList; //std::map<int,bool> mapSlotSignalledList;
//checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList); checkForLaggingClients(errorMsgList);
} }
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
@@ -1038,10 +1119,10 @@ void ServerInterface::update() {
difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) { difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) {
//printf("\nServerInterface::update -- F\n"); //printf("\nServerInterface::update -- F\n");
std::map<int,ConnectionSlotEvent> eventList; //std::map<int,ConnectionSlotEvent> eventList;
std::map<int,bool> mapSlotSignalledList; //std::map<int,bool> mapSlotSignalledList;
//checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList); checkForLaggingClients(errorMsgList);
} }
//printf("\nServerInterface::update -- G\n"); //printf("\nServerInterface::update -- G\n");

View File

@@ -209,6 +209,9 @@ protected:
void checkForLaggingClients(std::map<int,bool> &mapSlotSignalledList, std::map<int,ConnectionSlotEvent> &eventList, std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,std::vector <string> &errorMsgList); void checkForLaggingClients(std::map<int,bool> &mapSlotSignalledList, std::map<int,ConnectionSlotEvent> &eventList, std::map<PLATFORM_SOCKET,bool> &socketTriggeredList,std::vector <string> &errorMsgList);
void executeNetworkCommandsFromClients(); void executeNetworkCommandsFromClients();
void dispatchPendingChatMessages(std::vector <string> &errorMsgList); void dispatchPendingChatMessages(std::vector <string> &errorMsgList);
void waitForSignalledClients(std::map<int,bool> &mapSlotSignalledList,std::vector <string> &errorMsgList);
void checkForLaggingClients(std::vector <string> &errorMsgList);
}; };
}}//end namespace }}//end namespace

View File

@@ -116,13 +116,14 @@ protected:
//SimpleTaskThread *pingThread; //SimpleTaskThread *pingThread;
std::map<string,double> pingCache; std::map<string,double> pingCache;
time_t lastThreadedPing; time_t lastThreadedPing;
Mutex pingThreadAccessor; //Mutex pingThreadAccessor;
Mutex dataSynchAccessorRead; //Mutex dataSynchAccessorRead;
Mutex dataSynchAccessorWrite; //Mutex dataSynchAccessorWrite;
ReadWriteMutex dataSynchAccessorRWLMutex;
Mutex inSocketDestructorSynchAccessor; ReadWriteMutex inSocketDestructorSynchAccessor;
bool inSocketDestructor; //bool inSocketDestructor;
public: public:
Socket(PLATFORM_SOCKET sock); Socket(PLATFORM_SOCKET sock);

View File

@@ -24,6 +24,7 @@
//#include "util.h" //#include "util.h"
#include <vector> #include <vector>
#include "types.h"
#include "leak_dumper.h" #include "leak_dumper.h"
// ===================================================== // =====================================================
@@ -187,9 +188,131 @@ public:
Semaphore(Uint32 initialValue = 0); Semaphore(Uint32 initialValue = 0);
~Semaphore(); ~Semaphore();
void signal(); void signal();
int waitTillSignalled(); int waitTillSignalled(int waitMilliseconds=-1);
uint32 getSemValue();
}; };
class ReadWriteMutex
{
public:
ReadWriteMutex(int maxReaders = 32);
void LockRead();
void UnLockRead();
void LockWrite();
void UnLockWrite();
int maxReaders();
void setOwnerId(string ownerId) { this->ownerId = ownerId; }
private:
Semaphore semaphore;
Mutex mutex;
int maxReadersCount;
string ownerId;
};
class ReadWriteMutexSafeWrapper {
protected:
ReadWriteMutex *mutex;
string ownerId;
bool isReadLock;
#ifdef DEBUG_PERFORMANCE_MUTEXES
Chrono chrono;
#endif
public:
ReadWriteMutexSafeWrapper(ReadWriteMutex *mutex,bool isReadLock=true, string ownerId="") {
this->mutex = mutex;
this->isReadLock = isReadLock;
this->ownerId = ownerId;
Lock();
}
~ReadWriteMutexSafeWrapper() {
ReleaseLock();
}
void setReadWriteMutex(ReadWriteMutex *mutex,bool isReadLock=true,string ownerId="") {
this->mutex = mutex;
this->isReadLock = isReadLock;
this->ownerId = ownerId;
Lock();
}
bool isValidReadWriteMutex() const {
return(this->mutex != NULL);
}
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
#ifdef DEBUG_PERFORMANCE_MUTEXES
chrono.start();
#endif
if(this->isReadLock == true) {
this->mutex->LockRead();
}
else {
this->mutex->LockWrite();
}
#ifdef DEBUG_PERFORMANCE_MUTEXES
if(chrono.getMillis() > 5) printf("In [%s::%s Line: %d] MUTEX LOCK took msecs: %lld, this->mutex->getRefCount() = %d ownerId [%s]\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),this->mutex->getRefCount(),ownerId.c_str());
chrono.start();
#endif
#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
if(this->isReadLock == true) {
this->mutex->UnLockRead();
}
else {
this->mutex->UnLockWrite();
}
#ifdef DEBUG_PERFORMANCE_MUTEXES
if(chrono.getMillis() > 100) printf("In [%s::%s Line: %d] MUTEX UNLOCKED and held locked for msecs: %lld, this->mutex->getRefCount() = %d ownerId [%s]\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),this->mutex->getRefCount(),ownerId.c_str());
#endif
#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;
}
}
}
};
}}//end namespace }}//end namespace
#endif #endif

View File

@@ -780,26 +780,25 @@ bool Socket::isSocketValid(const PLATFORM_SOCKET *validateSocket) {
} }
Socket::Socket(PLATFORM_SOCKET sock) { Socket::Socket(PLATFORM_SOCKET sock) {
MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE); ReadWriteMutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,true,CODE_AT_LINE);
inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
this->inSocketDestructor = false; //this->inSocketDestructor = false;
//safeMutexSocketDestructorFlag.ReleaseLock(); //safeMutexSocketDestructorFlag.ReleaseLock();
//this->pingThread = NULL; //this->pingThread = NULL;
pingThreadAccessor.setOwnerId(CODE_AT_LINE); //pingThreadAccessor.setOwnerId(CODE_AT_LINE);
dataSynchAccessorRead.setOwnerId(CODE_AT_LINE); //dataSynchAccessorRead.setOwnerId(CODE_AT_LINE);
dataSynchAccessorWrite.setOwnerId(CODE_AT_LINE); //dataSynchAccessorWrite.setOwnerId(CODE_AT_LINE);
dataSynchAccessorRWLMutex.setOwnerId(CODE_AT_LINE);
this->sock= sock; this->sock= sock;
this->connectedIpAddress = ""; this->connectedIpAddress = "";
} }
Socket::Socket() { Socket::Socket() {
MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE); ReadWriteMutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,true,CODE_AT_LINE);
inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
this->inSocketDestructor = false; //this->inSocketDestructor = false;
//safeMutexSocketDestructorFlag.ReleaseLock(); //safeMutexSocketDestructorFlag.ReleaseLock();
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@@ -865,13 +864,13 @@ void Socket::simpleTask(BaseThread *callingThread) {
*/ */
Socket::~Socket() { Socket::~Socket() {
MutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,CODE_AT_LINE); ReadWriteMutexSafeWrapper safeMutexSocketDestructorFlag(&inSocketDestructorSynchAccessor,false,CODE_AT_LINE);
if(this->inSocketDestructor == true) { //if(this->inSocketDestructor == true) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__); // SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] this->inSocketDestructor == true\n",__FILE__,__FUNCTION__,__LINE__);
return; // return;
} //}
inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
this->inSocketDestructor = true; //this->inSocketDestructor = true;
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
@@ -880,12 +879,12 @@ Socket::~Socket() {
disconnectSocket(); disconnectSocket();
// Allow other callers with a lock on the mutexes to let them go // Allow other callers with a lock on the mutexes to let them go
for(time_t elapsed = time(NULL); //for(time_t elapsed = time(NULL);
(dataSynchAccessorRead.getRefCount() > 0 || // (dataSynchAccessorRead.getRefCount() > 0 ||
dataSynchAccessorWrite.getRefCount() > 0) && // dataSynchAccessorWrite.getRefCount() > 0) &&
difftime(time(NULL),elapsed) <= 5;) { // difftime(time(NULL),elapsed) <= 5;) {
//sleep(0); //sleep(0);
} //}
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
@@ -900,8 +899,9 @@ void Socket::disconnectSocket() {
if(isSocketValid() == true) { if(isSocketValid() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
MutexSafeWrapper safeMutex1(&dataSynchAccessorWrite,CODE_AT_LINE); //MutexSafeWrapper safeMutex1(&dataSynchAccessorWrite,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,false,CODE_AT_LINE);
::shutdown(sock,2); ::shutdown(sock,2);
#ifndef WIN32 #ifndef WIN32
::close(sock); ::close(sock);
@@ -910,8 +910,8 @@ void Socket::disconnectSocket() {
::closesocket(sock); ::closesocket(sock);
sock = -1; sock = -1;
#endif #endif
safeMutex.ReleaseLock(); //safeMutex.ReleaseLock();
safeMutex1.ReleaseLock(); //safeMutex1.ReleaseLock();
} }
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
@@ -1142,7 +1142,8 @@ int Socket::send(const void *data, int dataSize) {
// inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); // inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,false,CODE_AT_LINE);
#ifdef __APPLE__ #ifdef __APPLE__
bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE); bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE);
@@ -1159,7 +1160,7 @@ int Socket::send(const void *data, int dataSize) {
if(bytesSent < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) { if(bytesSent < 0 && getLastSocketError() != PLATFORM_SOCKET_TRY_AGAIN) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR WRITING SOCKET DATA, err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText().c_str()); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR WRITING SOCKET DATA, err = %d error = %s\n",__FILE__,__FUNCTION__,__LINE__,bytesSent,getLastSocketErrorFormattedText().c_str());
} }
else if(isConnected() == true && bytesSent < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) { else if(bytesSent < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN && isConnected() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__,__LINE__); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__,__LINE__);
int attemptCount = 0; int attemptCount = 0;
@@ -1180,7 +1181,8 @@ int Socket::send(const void *data, int dataSize) {
// inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); // inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,false,CODE_AT_LINE);
#ifdef __APPLE__ #ifdef __APPLE__
bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE); bytesSent = ::send(sock, (const char *)data, dataSize, SO_NOSIGPIPE);
#else #else
@@ -1229,7 +1231,8 @@ int Socket::send(const void *data, int dataSize) {
// inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); // inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorWrite,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,false,CODE_AT_LINE);
const char *sendBuf = (const char *)data; const char *sendBuf = (const char *)data;
#ifdef __APPLE__ #ifdef __APPLE__
bytesSent = ::send(sock, &sendBuf[totalBytesSent], dataSize - totalBytesSent, SO_NOSIGPIPE); bytesSent = ::send(sock, &sendBuf[totalBytesSent], dataSize - totalBytesSent, SO_NOSIGPIPE);
@@ -1294,7 +1297,8 @@ int Socket::receive(void *data, int dataSize, bool tryReceiveUntilDataSizeMet) {
// inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); // inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0); bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
} }
@@ -1323,7 +1327,8 @@ int Socket::receive(void *data, int dataSize, bool tryReceiveUntilDataSizeMet) {
// inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE); // inSocketDestructorSynchAccessor.setOwnerId(CODE_AT_LINE);
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0); bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@@ -1382,7 +1387,8 @@ int Socket::peek(void *data, int dataSize,bool mustGetData) {
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
//MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize)); //MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize));
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis()); //if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
@@ -1421,7 +1427,8 @@ int Socket::peek(void *data, int dataSize,bool mustGetData) {
// safeMutexSocketDestructorFlag.ReleaseLock(); // safeMutexSocketDestructorFlag.ReleaseLock();
//MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize)); //MutexSafeWrapper safeMutex(&dataSynchAccessor,CODE_AT_LINE + "_" + intToStr(sock) + "_" + intToStr(dataSize));
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK); err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@@ -1716,7 +1723,8 @@ void ClientSocket::connect(const Ip &ip, int port)
FD_SET(sock, &myset); FD_SET(sock, &myset);
{ {
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
err = select((int)sock + 1, NULL, &myset, NULL, &tv); err = select((int)sock + 1, NULL, &myset, NULL, &tv);
//safeMutex.ReleaseLock(); //safeMutex.ReleaseLock();
} }
@@ -2132,7 +2140,8 @@ Socket *ServerSocket::accept() {
struct sockaddr_in cli_addr; struct sockaddr_in cli_addr;
socklen_t clilen = sizeof(cli_addr); socklen_t clilen = sizeof(cli_addr);
char client_host[100]=""; char client_host[100]="";
MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE); //MutexSafeWrapper safeMutex(&dataSynchAccessorRead,CODE_AT_LINE);
ReadWriteMutexSafeWrapper safeMutex(&dataSynchAccessorRWLMutex,true,CODE_AT_LINE);
PLATFORM_SOCKET newSock= ::accept(sock, (struct sockaddr *) &cli_addr, &clilen); PLATFORM_SOCKET newSock= ::accept(sock, (struct sockaddr *) &cli_addr, &clilen);
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();

View File

@@ -210,14 +210,59 @@ void Semaphore::signal() {
SDL_SemPost(semaphore); SDL_SemPost(semaphore);
} }
int Semaphore::waitTillSignalled() { int Semaphore::waitTillSignalled(int waitMilliseconds) {
if(semaphore == NULL) { if(semaphore == NULL) {
char szBuf[1024]=""; char szBuf[1024]="";
snprintf(szBuf,1023,"In [%s::%s Line: %d] semaphore == NULL",__FILE__,__FUNCTION__,__LINE__); snprintf(szBuf,1023,"In [%s::%s Line: %d] semaphore == NULL",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(szBuf); throw runtime_error(szBuf);
} }
int semValue = SDL_SemWait(semaphore); int semValue = 0;
if(waitMilliseconds >= 0) {
semValue = SDL_SemWaitTimeout(semaphore,waitMilliseconds);
}
else {
semValue = SDL_SemWait(semaphore);
}
return semValue; return semValue;
} }
uint32 Semaphore::getSemValue() {
if(semaphore == NULL) {
char szBuf[1024]="";
snprintf(szBuf,1023,"In [%s::%s Line: %d] semaphore == NULL",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(szBuf);
}
return SDL_SemValue(semaphore);
}
ReadWriteMutex::ReadWriteMutex(int maxReaders) : semaphore(maxReaders) {
this->maxReadersCount = maxReaders;
}
void ReadWriteMutex::LockRead() {
semaphore.waitTillSignalled();
}
void ReadWriteMutex::UnLockRead() {
semaphore.signal();
}
void ReadWriteMutex::LockWrite() {
MutexSafeWrapper safeMutex(&mutex);
uint32 totalLocks = maxReaders();
for (int i = 0; i < totalLocks; ++i) {
semaphore.waitTillSignalled();
}
}
void ReadWriteMutex::UnLockWrite() {
uint32 totalLocks = maxReaders();
for (int i = 0; i < totalLocks; ++i) {
semaphore.signal();
}
}
int ReadWriteMutex::maxReaders() {
//return semaphore.getSemValue();
return this->maxReadersCount;
}
}}//end namespace }}//end namespace