- attempt to fix threaded client stability and fixed some server side network bugs to also improve its stability

This commit is contained in:
Mark Vejvoda 2013-03-09 20:57:06 +00:00
parent 760ba99fd7
commit ac992b431d
7 changed files with 261 additions and 31 deletions

View File

@ -37,6 +37,115 @@ using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class ClientInterfaceThread
// =====================================================
ClientInterfaceThread::ClientInterfaceThread(ClientInterface *client) : BaseThread() {
//this->triggerIdMutex = new Mutex();
this->clientInterface = client;
//this->masterController = NULL;
}
ClientInterfaceThread::~ClientInterfaceThread() {
this->clientInterface = NULL;
//this->masterController = NULL;
//delete this->triggerIdMutex;
//this->triggerIdMutex = NULL;
}
void ClientInterfaceThread::setQuitStatus(bool value) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
BaseThread::setQuitStatus(value);
// if(value == true) {
// semTaskSignalled.signal();
// }
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
bool ClientInterfaceThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
bool ret = (getExecutingTask() == false);
if(ret == false && deleteSelfIfShutdownDelayed == true) {
setDeleteSelfOnExecutionDone(deleteSelfIfShutdownDelayed);
signalQuit();
}
return ret;
}
void ClientInterfaceThread::execute() {
RunningStatusSafeWrapper runningStatus(this);
try {
//setRunningStatus(true);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** STARTING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
bool minorDebugPerformance = false;
Chrono chrono;
//unsigned int idx = 0;
for(;this->clientInterface != NULL;) {
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//semTaskSignalled.waitTillSignalled();
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//static string masterSlaveOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
//MasterSlaveThreadControllerSafeWrapper safeMasterController(masterController,20000,masterSlaveOwnerId);
//printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
ExecutingTaskSafeWrapper safeExecutingTaskMutex(this);
//Chrono chrono;
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
//printf("START === Client thread ended\n");
while(this->getQuitStatus() == false && clientInterface != NULL) {
clientInterface->updateNetworkFrame();
}
//printf("END === Client thread ended\n");
//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(getQuitStatus() == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] ****************** ENDING worker thread this = %p\n",__FILE__,__FUNCTION__,__LINE__,this);
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw megaglest_runtime_error(ex.what());
}
catch(...) {
char szBuf[8096]="";
snprintf(szBuf,8096,"In [%s::%s %d] UNKNOWN error\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
throw megaglest_runtime_error(szBuf);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
// =====================================================
// class ClientInterface
// =====================================================
@ -113,7 +222,6 @@ ClientInterface::~ClientInterface() {
MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE);
shutdownNetworkCommandListThread();
//printf("A === Client destructor\n");
if(clientSocket != NULL && clientSocket->isConnected() == true) {
@ -735,6 +843,10 @@ void ClientInterface::updateLobby() {
}
}
void ClientInterface::updateNetworkFrame() {
this->updateFrame(NULL);
}
void ClientInterface::updateFrame(int *checkFrame) {
//printf("#1 ClientInterface::updateFrame\n");
@ -1019,20 +1131,20 @@ uint64 ClientInterface::getCachedLastPendingFrameCount() {
return result;
}
void ClientInterface::simpleTask(BaseThread *callingThread) {
Chrono chrono;
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
//printf("START === Client thread ended\n");
while(callingThread->getQuitStatus() == false && this->quitThread == false) {
updateFrame(NULL);
}
//printf("END === Client thread ended\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
}
//void ClientInterface::simpleTask(BaseThread *callingThread) {
// Chrono chrono;
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
//
// //printf("START === Client thread ended\n");
//
// while(callingThread->getQuitStatus() == false && this->quitThread == false) {
// updateFrame(NULL);
// }
//
// //printf("END === Client thread ended\n");
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
//}
bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPendingCommandsIndex) {
bool result = false;
@ -1108,9 +1220,13 @@ void ClientInterface::updateKeyframe(int frameCount) {
else {
if(networkCommandListThread == NULL) {
static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
networkCommandListThread = new SimpleTaskThread(this,0,0);
// networkCommandListThread = new SimpleTaskThread(this,0,0);
// networkCommandListThread->setUniqueID(mutexOwnerId);
// networkCommandListThread->start();
networkCommandListThread = new ClientInterfaceThread(this);
networkCommandListThread->setUniqueID(mutexOwnerId);
networkCommandListThread->start();
sleep(0);
}

View File

@ -28,12 +28,36 @@ using std::vector;
namespace Glest{ namespace Game{
class ClientInterface;
class ClientInterfaceThread : public BaseThread, public SlaveThreadControllerInterface {
protected:
ClientInterface *clientInterface;
//Semaphore semTaskSignalled;
//Mutex *triggerIdMutex;
//MasterSlaveThreadController *masterController;
virtual void setQuitStatus(bool value);
public:
ClientInterfaceThread(ClientInterface *client);
virtual ~ClientInterfaceThread();
virtual void execute();
//virtual void setMasterController(MasterSlaveThreadController *master) { masterController = master; }
virtual void setMasterController(MasterSlaveThreadController *master) { }
virtual void signalSlave(void *userdata) { }
virtual bool canShutdown(bool deleteSelfIfShutdownDelayed=false);
};
// =====================================================
// class ClientInterface
// =====================================================
class ClientInterface: public GameNetworkInterface,
public SimpleTaskCallbackInterface {
class ClientInterface: public GameNetworkInterface {
//public SimpleTaskCallbackInterface {
private:
static const int messageWaitTimeout;
static const int waitSleepTime;
@ -62,7 +86,9 @@ private:
int sessionKey;
int serverFTPPort;
SimpleTaskThread *networkCommandListThread;
//SimpleTaskThread *networkCommandListThread;
ClientInterfaceThread *networkCommandListThread;
Mutex *networkCommandListThreadAccessor;
std::map<int,Commands> cachedPendingCommands; //commands ready to be given
uint64 cachedPendingCommandsIndex;
@ -152,7 +178,8 @@ public:
void broadcastGameSetup(const GameSettings *gameSettings);
void broadcastGameStart(const GameSettings *gameSettings);
virtual void simpleTask(BaseThread *callingThread);
//virtual void simpleTask(BaseThread *callingThread);
void updateNetworkFrame();
virtual void saveGame(XmlNode *rootNode) {};

View File

@ -325,6 +325,7 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex
this->canAcceptConnections = true;
this->startInGameConnectionLaunch = false;
this->sentSavedGameInfo = false;
this->unPauseForInGameConnection = false;
this->skipLagCheck = false;
this->joinGameInProgress = false;
@ -1459,6 +1460,7 @@ void ConnectionSlot::close() {
this->skipLagCheck = false;
this->joinGameInProgress = false;
this->sentSavedGameInfo = false;
this->unPauseForInGameConnection = false;
this->ready= false;
this->connectedTime = 0;

View File

@ -40,6 +40,35 @@ DisplayMessageFunction NetworkInterface::pCB_DisplayMessage = NULL;
Vec3f MarkedCell::static_system_marker_color(MAGENTA.x,MAGENTA.y,MAGENTA.z);
NetworkInterface::NetworkInterface() {
networkAccessMutex = new Mutex();
}
NetworkInterface::~NetworkInterface() {
delete networkAccessMutex;
networkAccessMutex = NULL;
}
void NetworkInterface::addChatInfo(const ChatMsgInfo &msg) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
chatTextList.push_back(msg);
}
void NetworkInterface::addMarkedCell(const MarkedCell &msg) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
markedCellList.push_back(msg);
}
void NetworkInterface::addUnMarkedCell(const UnMarkedCell &msg) {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
unmarkedCellList.push_back(msg);
}
void NetworkInterface::sendMessage(NetworkMessage* networkMessage){
Socket* socket= getSocket(false);
@ -112,6 +141,10 @@ void NetworkInterface::DisplayErrorMessage(string sErr, bool closeSocket) {
std::vector<ChatMsgInfo> NetworkInterface::getChatTextList(bool clearList) {
std::vector<ChatMsgInfo> result;
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(chatTextList.empty() == false) {
result = chatTextList;
@ -123,6 +156,9 @@ std::vector<ChatMsgInfo> NetworkInterface::getChatTextList(bool clearList) {
}
void NetworkInterface::clearChatInfo() {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(chatTextList.empty() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] chatTextList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chatTextList.size());
chatTextList.clear();
@ -131,6 +167,10 @@ void NetworkInterface::clearChatInfo() {
std::vector<MarkedCell> NetworkInterface::getMarkedCellList(bool clearList) {
std::vector<MarkedCell> result;
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(markedCellList.empty() == false) {
result = markedCellList;
@ -142,6 +182,9 @@ std::vector<MarkedCell> NetworkInterface::getMarkedCellList(bool clearList) {
}
void NetworkInterface::clearMarkedCellList() {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(markedCellList.empty() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] markedCellList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,markedCellList.size());
markedCellList.clear();
@ -150,6 +193,10 @@ void NetworkInterface::clearMarkedCellList() {
std::vector<UnMarkedCell> NetworkInterface::getUnMarkedCellList(bool clearList) {
std::vector<UnMarkedCell> result;
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(unmarkedCellList.empty() == false) {
result = unmarkedCellList;
@ -161,6 +208,9 @@ std::vector<UnMarkedCell> NetworkInterface::getUnMarkedCellList(bool clearList)
}
void NetworkInterface::clearUnMarkedCellList() {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(unmarkedCellList.empty() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unmarkedCellList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,unmarkedCellList.size());
unmarkedCellList.clear();
@ -169,6 +219,10 @@ void NetworkInterface::clearUnMarkedCellList() {
std::vector<MarkedCell> NetworkInterface::getHighlightedCellList(bool clearList) {
std::vector<MarkedCell> result;
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(highlightedCellList.empty() == false) {
result = highlightedCellList;
@ -180,6 +234,9 @@ std::vector<MarkedCell> NetworkInterface::getHighlightedCellList(bool clearList)
}
void NetworkInterface::clearHighlightedCellList() {
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
if(highlightedCellList.empty() == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] markedCellList.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,markedCellList.size());
highlightedCellList.clear();
@ -187,6 +244,9 @@ void NetworkInterface::clearHighlightedCellList() {
}
void NetworkInterface::setHighlightedCell(const MarkedCell &msg){
static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
MutexSafeWrapper safeMutex(networkAccessMutex,mutexOwnerId);
for(int idx = 0; idx < highlightedCellList.size(); idx++) {
MarkedCell mc = highlightedCellList[idx];
if(mc.getFactionIndex()==msg.getFactionIndex()){

View File

@ -185,12 +185,15 @@ protected:
std::vector<MarkedCell> highlightedCellList;
Mutex *networkAccessMutex;
public:
static const int readyWaitTimeout;
GameSettings gameSettings;
public:
virtual ~NetworkInterface(){}
NetworkInterface();
virtual ~NetworkInterface();
virtual Socket* getSocket(bool mutexLock=true)= 0;
virtual void close()= 0;
@ -228,15 +231,15 @@ public:
std::vector<ChatMsgInfo> getChatTextList(bool clearList);
void clearChatInfo();
void addChatInfo(const ChatMsgInfo &msg) { chatTextList.push_back(msg); }
void addChatInfo(const ChatMsgInfo &msg);
std::vector<MarkedCell> getMarkedCellList(bool clearList);
void clearMarkedCellList();
void addMarkedCell(const MarkedCell &msg) { markedCellList.push_back(msg); }
void addMarkedCell(const MarkedCell &msg);
std::vector<UnMarkedCell> getUnMarkedCellList(bool clearList);
void clearUnMarkedCellList();
void addUnMarkedCell(const UnMarkedCell &msg) { unmarkedCellList.push_back(msg); }
void addUnMarkedCell(const UnMarkedCell &msg);
std::vector<MarkedCell> getHighlightedCellList(bool clearList);
void clearHighlightedCellList();

View File

@ -1816,17 +1816,17 @@ const CommandType *Unit::computeCommandType(const Vec2i &pos, const Unit *target
targetUnit->getType() != NULL &&
targetUnit->getType()->getStore(this->getLoadType()) > 0) {
const HarvestCommandType *previousHarvestCmd = this->getType()->getFirstHarvestCommand(this->getLoadType(),this->getFaction());
if(previousHarvestCmd != NULL) {
//const HarvestCommandType *previousHarvestCmd = this->getType()->getFirstHarvestCommand(this->getLoadType(),this->getFaction());
//if(previousHarvestCmd != NULL) {
//printf("\n#1 return harvested resources\n\n");
//this->setCurrSkill(previousHarvestCmd->getStopLoadedSkillType()); // make sure we use the right harvest animation
commandType = type->getFirstHarvestEmergencyReturnCommand();
}
else {
commandType = type->getFirstHarvestEmergencyReturnCommand();
//}
//else {
//printf("\n#2 return harvested resources\n\n");
//this->setCurrSkill(hct->getStopLoadedSkillType());
commandType = type->getFirstHarvestEmergencyReturnCommand();
}
// commandType = type->getFirstHarvestEmergencyReturnCommand();
//}
}
}
}

View File

@ -348,6 +348,28 @@ void World::init(Game *game, bool createUnits, bool initFactions){
if(loadWorldNode != NULL) {
map.loadGame(loadWorldNode,this);
if(fogOfWar == false) {
for(int i=0; i< map.getSurfaceW(); ++i) {
for(int j=0; j< map.getSurfaceH(); ++j) {
SurfaceCell *sc= map.getSurfaceCell(i, j);
if(sc == NULL) {
throw megaglest_runtime_error("sc == NULL");
}
for (int k = 0; k < GameConstants::maxPlayers; k++) {
//sc->setExplored(k, (game->getGameSettings()->getFlagTypes1() & ft1_show_map_resources) == ft1_show_map_resources);
sc->setVisible(k, !fogOfWar);
}
for (int k = GameConstants::maxPlayers; k < GameConstants::maxPlayers + GameConstants::specialFactions; k++) {
sc->setExplored(k, true);
sc->setVisible(k, true);
}
}
}
}
minimap.loadGame(loadWorldNode);
}