From a02a32c0298d1fe47040846e1c122f3307e2ea91 Mon Sep 17 00:00:00 2001 From: Dennis Andersen Date: Thu, 9 Jan 2014 14:18:01 +0100 Subject: [PATCH] Network now closes listener gracefully, meaning threads dont crash anymore, also fixed a minor bug in Game folder --- Code/Game/DanBiasGame/DanBiasGame_Impl.cpp | 26 ++-- Code/Game/DanBiasServer/GameServer.cpp | 10 +- .../DanBiasServer/GameSession/GameSession.cpp | 9 +- .../GameSession/GameSessionManager.cpp | 9 +- .../GameSession/GameSessionManager.h | 5 + .../DanBiasServer/LobbySessions/MainLobby.cpp | 5 +- Code/Misc/Thread/OysterThread_Impl.cpp | 114 +++--------------- Code/Network/NetworkAPI/NetworkClient.cpp | 4 +- Code/Network/NetworkDependencies/Listener.cpp | 40 +++++- Code/Network/NetworkDependencies/Listener.h | 5 +- 10 files changed, 101 insertions(+), 126 deletions(-) diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp index 57d47292..0edbce01 100644 --- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp +++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp @@ -96,19 +96,29 @@ namespace DanBias break; case protocol_Gameplay_ObjectPosition: { - - Client::GameClientState::ObjPos* protocolData = new Client::GameClientState::ObjPos; - protocolData->object_ID = p[1].value.netInt; + Client::GameClientState::ObjPos protocolData; + protocolData.object_ID = p[1].value.netInt; for(int i = 0; i< 16; i++) { - protocolData->worldPos[i] = p[i+2].value.netFloat; + protocolData.worldPos[i] = p[i+2].value.netFloat; } if(dynamic_cast(gameClientState)) - ((Client::GameState*)gameClientState)->Protocol(protocolData); + ((Client::GameState*)gameClientState)->Protocol(&protocolData); - delete protocolData; - protocolData = NULL; + //Why use dynamicly allocated memory when data dies after block? + //Client::GameClientState::ObjPos* protocolData = new Client::GameClientState::ObjPos; + //protocolData->object_ID = p[1].value.netInt; + //for(int i = 0; i< 16; i++) + //{ + // protocolData->worldPos[i] = p[i+2].value.netFloat; + //} + // + //if(dynamic_cast(gameClientState)) + // ((Client::GameState*)gameClientState)->Protocol(protocolData); + // + //delete protocolData; + //protocolData = NULL; } break; @@ -159,7 +169,7 @@ namespace DanBias m_data->recieverObj = new MyRecieverObject; - // m_data->recieverObj->nwClient = new Oyster::Network::NetworkClient(m_data->recieverObj, Oyster::Network::NetworkProtocolCallbackType_Object); + m_data->recieverObj->nwClient = new Oyster::Network::NetworkClient(m_data->recieverObj, Oyster::Network::NetworkProtocolCallbackType_Object); m_data->recieverObj->nwClient->Connect(desc.port, desc.IP); if (!m_data->recieverObj->nwClient->IsConnected()) diff --git a/Code/Game/DanBiasServer/GameServer.cpp b/Code/Game/DanBiasServer/GameServer.cpp index 837d52b0..a5210123 100644 --- a/Code/Game/DanBiasServer/GameServer.cpp +++ b/Code/Game/DanBiasServer/GameServer.cpp @@ -25,7 +25,8 @@ namespace DanBias void GameServer::NetworkCallback(NetworkClient* client) { - static GameSession *myTest = 0; + static bool myTest = false; + static int sessionId = -1; printf("Client with ID [%i] connected.\n", client->GetID()); if(!myTest) @@ -36,10 +37,9 @@ namespace DanBias desc.mapName = L"test"; desc.clients.Push(c); desc.exitDestionation = this->mainLobby; - int sessionId = 0; if((sessionId = GameSessionManager::AddSession(desc, true)) == 0) printf("Failed to create a game session"); - + myTest = true; //myTest = new GameSession(); // //DanBias::GameSession::GameSessionDescription desc; @@ -52,7 +52,7 @@ namespace DanBias else { Utility::DynamicMemory::SmartPointer c = new LobbyClient(client); - myTest->Join(c); + GameSessionManager::JoinSession(sessionId, c); } @@ -119,6 +119,8 @@ namespace DanBias } DanBiasServerReturn GameServer::Release() { + GameSessionManager::CloseSession(); + this->mainLobby->Release(); delete this->mainLobby; this->server->Shutdown(); delete this->server; diff --git a/Code/Game/DanBiasServer/GameSession/GameSession.cpp b/Code/Game/DanBiasServer/GameSession/GameSession.cpp index 866626c4..706a575c 100644 --- a/Code/Game/DanBiasServer/GameSession/GameSession.cpp +++ b/Code/Game/DanBiasServer/GameSession/GameSession.cpp @@ -29,6 +29,7 @@ namespace DanBias return; } } + clients.Push(obj); } void RemoveObject(DynamicArray>& clients, DanBias::GameClient* obj) { @@ -165,10 +166,8 @@ namespace DanBias if(p[6].value.netBool) //bool bStrafeLeft; c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_LEFT); - //Oyster::Math::Float4x4 p; - Protocol_ObjectPosition op;//(c.GetPlayer()->GetRigidBody(), c.GetPlayer()->GetID()); - //op.object_ID = c.GetPlayer()->GetID(); - Send(op.GetProtocol()); + //Protocol_ObjectPosition op(c->GetPlayer()->GetOrientation(), c->GetPlayer()->GetID()); + //Send(op.GetProtocol()); } break; case protocol_Gameplay_PlayerMouseMovement: @@ -197,7 +196,7 @@ namespace DanBias break; case GameLogic::Protocol_General_Status::States_disconected: - printf("Client with ID [%i] dissconnected", c->GetClient()->GetID()); + printf("Client with ID [%i] dissconnected\n", c->GetClient()->GetID()); RemoveObject(this->clients, c); break; diff --git a/Code/Game/DanBiasServer/GameSession/GameSessionManager.cpp b/Code/Game/DanBiasServer/GameSession/GameSessionManager.cpp index ee7c191f..23dadb65 100644 --- a/Code/Game/DanBiasServer/GameSession/GameSessionManager.cpp +++ b/Code/Game/DanBiasServer/GameSession/GameSessionManager.cpp @@ -78,7 +78,7 @@ bool GameSessionManager::StartSession(int session) bool GameSessionManager::JoinSession(int session, Utility::DynamicMemory::SmartPointer client) { int i = -1; - if((i = gameSessionData.Existst(session)) != -1) return false; + if((i = gameSessionData.Existst(session)) == -1) return false; gameSessionData.sessions[i]->Join(client); @@ -97,6 +97,13 @@ void GameSessionManager::GetSessionInfo(int session, GameSessionInfo& data) //data.numberOfPlayers = gameSessionData.sessions[i]-> } +void GameSessionManager::CloseSession() +{ + for (unsigned int i = 0; i < gameSessionData.sessions.Size(); i++) + { + gameSessionData.sessions[i]->CloseSession(); + } +} void GameSessionManager::CloseSession(int session) { int i = -1; diff --git a/Code/Game/DanBiasServer/GameSession/GameSessionManager.h b/Code/Game/DanBiasServer/GameSession/GameSessionManager.h index 4f93232b..75b0e64d 100644 --- a/Code/Game/DanBiasServer/GameSession/GameSessionManager.h +++ b/Code/Game/DanBiasServer/GameSession/GameSessionManager.h @@ -64,6 +64,11 @@ namespace DanBias */ static void CloseSession(int session); + /** + * Close all sessions. + */ + static void CloseSession(); + /** * Get total sessions running * @return Returns the total sessions curently running. diff --git a/Code/Game/DanBiasServer/LobbySessions/MainLobby.cpp b/Code/Game/DanBiasServer/LobbySessions/MainLobby.cpp index fd31f445..9b8899ca 100644 --- a/Code/Game/DanBiasServer/LobbySessions/MainLobby.cpp +++ b/Code/Game/DanBiasServer/LobbySessions/MainLobby.cpp @@ -19,11 +19,12 @@ namespace DanBias } MainLobby::~MainLobby() { - delete this->box; - this->box = 0; + } void MainLobby::Release() { + delete this->box; + this->box = 0; this->CloseSession(true); } diff --git a/Code/Misc/Thread/OysterThread_Impl.cpp b/Code/Misc/Thread/OysterThread_Impl.cpp index ab7f6ac6..16668c04 100644 --- a/Code/Misc/Thread/OysterThread_Impl.cpp +++ b/Code/Misc/Thread/OysterThread_Impl.cpp @@ -15,8 +15,6 @@ using namespace Oyster::Thread; using namespace Utility::DynamicMemory; - - #pragma region Declerations enum OYSTER_THREAD_STATE @@ -51,8 +49,8 @@ using namespace Utility::DynamicMemory; OwnerContainer ownerObj; // std::atomic msec; //threadData->state = OYSTER_THREAD_STATE_DEAD; - if(wait) + if(this->workerThread.joinable()) { - if(std::this_thread::get_id() != this->workerThread.get_id()) - if(this->workerThread.joinable()) - { - this->workerThread.join(); - this->isCreated = false; - this->threadData = 0; - } - } - else - { - if(this->workerThread.joinable()) - this->workerThread.detach(); + this->workerThread.join(); + this->isCreated = false; + delete this->threadData; + this->threadData = 0; } + return OYSTER_THREAD_ERROR_SUCCESS; } - //OYSTER_THREAD_ERROR Create(ThreadFunction fnc, IThreadObject* worker, bool start, bool detach) - //{ - // if(this->isCreated ) return OYSTER_THREAD_ERROR_ThreadAlreadyCreated; - // - // threadData = new ThreadData(); - // if(start) - // this->threadData->state = OYSTER_THREAD_STATE_NORMAL; - // else - // this->threadData->state = OYSTER_THREAD_STATE_IDLE; - // threadData->owner = worker; - // threadData->prio = OYSTER_THREAD_PRIORITY_3; - // - // workerThread = std::thread(fnc, this->threadData); - // - // if(detach) - // this->workerThread.detach(); - // - // isCreated = true; - // - // return OYSTER_THREAD_ERROR_SUCCESS; - //} - //OYSTER_THREAD_ERROR Create(ThreadFunction fnc, Oyster::Callback::OysterCallback worker, bool start, bool detach) - //{ - // if(this->isCreated ) return OYSTER_THREAD_ERROR_ThreadAlreadyCreated; - // - // threadData = new ThreadData(); - // if(start) - // this->threadData->state = OYSTER_THREAD_STATE_NORMAL; - // else - // this->threadData->state = OYSTER_THREAD_STATE_IDLE; - // threadData->ownerObj = worker; - // threadData->prio = OYSTER_THREAD_PRIORITY_3; - // - // workerThread = std::thread(fnc, this->threadData); - // - // if(detach) - // this->workerThread.detach(); - // - // isCreated = true; - // - // return OYSTER_THREAD_ERROR_SUCCESS; - //} OYSTER_THREAD_ERROR Create(ThreadFunction fnc, OwnerContainer worker, bool start, bool detach) { if(this->isCreated ) return OYSTER_THREAD_ERROR_ThreadAlreadyCreated; - + threadData = new ThreadData(); if(start) this->threadData->state = OYSTER_THREAD_STATE_NORMAL; @@ -155,8 +105,8 @@ using namespace Utility::DynamicMemory; workerThread = std::thread(fnc, this->threadData); - if(detach) - this->workerThread.detach(); + //if(detach) + // this->workerThread.detach(); isCreated = true; @@ -171,9 +121,7 @@ using namespace Utility::DynamicMemory; PrivateData(){} ~PrivateData() { - if(data) - if(data->threadData) - memset(&data->threadData->ownerObj, 0, sizeof(OwnerContainer)); + data.Release(); } OYSTER_THREAD_ERROR Create(ThreadFunction fnc, OwnerContainer worker, bool start, bool detach) { @@ -248,7 +196,8 @@ using namespace Utility::DynamicMemory; if(w->ownerObj.value.obj) w->ownerObj.value.obj->ThreadExit(); w->state = OYSTER_THREAD_STATE_DEAD; - delete w; + + //delete w; } }; @@ -295,31 +244,6 @@ OYSTER_THREAD_ERROR OysterThread::Create(ThreadFnc worker, bool start, bool deta return this->privateData->Create(ThreadHelp::ThreadingFunction, c, start, detach); } -/* -OYSTER_THREAD_ERROR OysterThread::Create(Oyster::Callback::CallbackObject* worker, bool start, bool detach) -{ - if(!this->privateData) - this->privateData = new PrivateData(); - - Oyster::Callback::OysterCallback<> temp; - temp.callbackType = Oyster::Callback::CallbackType_Object; - temp.value = worker; - - return this->privateData->Create(ThreadHelp::ThreadingFunction, temp, start, detach); -} -OYSTER_THREAD_ERROR OysterThread::Create(Oyster::Callback::CallbackFunction::FNC worker, bool start, bool detach) -{ - if(!this->privateData) - this->privateData = new PrivateData(); - - Oyster::Callback::OysterCallback<> temp; - temp.callbackType = Oyster::Callback::CallbackType_Function; - temp.value = worker; - - return this->privateData->Create(ThreadHelp::ThreadingFunction, temp, start, detach); -} -*/ - OYSTER_THREAD_ERROR OysterThread::Start() { if(!this->privateData->data->threadData->ownerObj) @@ -384,9 +308,6 @@ OYSTER_THREAD_ERROR OysterThread::Wait() if( this->privateData->data->workerThread.get_id() == std::this_thread::get_id()) return OYSTER_THREAD_ERROR_ThreadCannotWaintOnItselfe; - - //this->privateData->data->threadData->threadFunctionLock.lock(); - //this->privateData->data->threadData->threadFunctionLock.unlock(); return OYSTER_THREAD_ERROR_SUCCESS; } @@ -394,9 +315,6 @@ OYSTER_THREAD_ERROR OysterThread::Wait(int msec) { if(this->privateData->data->workerThread.get_id() == std::this_thread::get_id()) return OYSTER_THREAD_ERROR_ThreadCannotWaintOnItselfe; - - //if(this->privateData->data->threadData->threadFunctionLock.try_lock_for(std::chrono::milliseconds(msec))) - // this->privateData->data->threadData->threadFunctionLock.unlock(); return OYSTER_THREAD_ERROR_SUCCESS; } diff --git a/Code/Network/NetworkAPI/NetworkClient.cpp b/Code/Network/NetworkAPI/NetworkClient.cpp index f8c55476..2a0c4dc0 100644 --- a/Code/Network/NetworkAPI/NetworkClient.cpp +++ b/Code/Network/NetworkAPI/NetworkClient.cpp @@ -63,9 +63,8 @@ struct ClientDataContainer } ~ClientDataContainer() { - thread.Stop(); - thread.Wait(); connection.Disconnect(); + thread.Stop(); callbackType = NetworkProtocolCallbackType_Unknown; ShutdownWinSock(); @@ -244,6 +243,7 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[]) void NetworkClient::Disconnect() { privateData->data->connection.Disconnect(); + privateData->data->thread.Terminate(); } bool NetworkClient::IsConnected() diff --git a/Code/Network/NetworkDependencies/Listener.cpp b/Code/Network/NetworkDependencies/Listener.cpp index 6f3aaa37..deb0d992 100644 --- a/Code/Network/NetworkDependencies/Listener.cpp +++ b/Code/Network/NetworkDependencies/Listener.cpp @@ -6,11 +6,14 @@ using namespace Oyster::Thread; Listener::Listener() { + this->port = -1; + this->isListening = false; connection = NULL; } Listener::Listener(Oyster::Network::IPostBox* postBox) { + this->isListening = false; connection = NULL; this->postBox = postBox; } @@ -19,9 +22,11 @@ Listener::~Listener() { if(connection) { - this->thread.Terminate(false); + this->isListening = false; + this->thread.Terminate(); delete connection; connection = 0; + this->port = -1; } } @@ -36,6 +41,8 @@ bool Listener::Init(unsigned int port) return false; } + this->port = port; + this->isListening = true; return true; } @@ -52,6 +59,11 @@ bool Listener::Init(unsigned int port, bool start) return false; } + if(start) + { + this->isListening = true; + } + this->port = port; return true; } @@ -62,17 +74,18 @@ bool Listener::Start() return false; } + this->isListening = true; return true; } void Listener::Stop() { - thread.Stop(); + StopListen(); } void Listener::Shutdown() { - thread.Stop(false); + StopListen(); } void Listener::SetPostBox(Oyster::Network::IPostBox* postBox) @@ -87,6 +100,10 @@ int Listener::Accept() int clientSocket = -1; clientSocket = connection->Listen(); + if(!this->isListening.load()) + { + return -1; + } if(clientSocket != -1) { stdMutex.lock(); @@ -96,13 +113,26 @@ int Listener::Accept() return clientSocket; } - +void Listener::StopListen() +{ + if(this->connection && this->connection->IsConnected()) + { + this->isListening = false; + Connection c; + c.InitiateClient(); + c.Connect(this->port, "127.0.0.1"); + } +} bool Listener::DoWork() { if(!this->connection) return false; int result = Accept(); - if(result == -1) + if(!this->isListening.load()) + { + return false; + } + else if(result == -1) { //Do something? } diff --git a/Code/Network/NetworkDependencies/Listener.h b/Code/Network/NetworkDependencies/Listener.h index b45dc1f4..422592e7 100644 --- a/Code/Network/NetworkDependencies/Listener.h +++ b/Code/Network/NetworkDependencies/Listener.h @@ -11,6 +11,7 @@ #include "../../Misc/Thread/OysterThread.h" #include "../../Misc/Thread/OysterMutex.h" #include "../../Misc/Utilities.h" +#include namespace Oyster { @@ -41,6 +42,7 @@ namespace Oyster //Function that runs in the thread. int Accept(); + void StopListen(); private: ::Oyster::Network::Connection* connection; @@ -50,7 +52,8 @@ namespace Oyster std::mutex stdMutex; IPostBox* postBox; - + std::atomic isListening; + int port; }; } }