Network now closes listener gracefully, meaning threads dont crash anymore, also fixed a minor bug in Game folder

This commit is contained in:
Dennis Andersen 2014-01-09 14:18:01 +01:00
parent 42de421904
commit a02a32c029
10 changed files with 101 additions and 126 deletions

View File

@ -96,19 +96,29 @@ namespace DanBias
break; break;
case protocol_Gameplay_ObjectPosition: case protocol_Gameplay_ObjectPosition:
{ {
Client::GameClientState::ObjPos protocolData;
Client::GameClientState::ObjPos* protocolData = new Client::GameClientState::ObjPos; protocolData.object_ID = p[1].value.netInt;
protocolData->object_ID = p[1].value.netInt;
for(int i = 0; i< 16; i++) 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<Client::GameState*>(gameClientState)) if(dynamic_cast<Client::GameState*>(gameClientState))
((Client::GameState*)gameClientState)->Protocol(protocolData); ((Client::GameState*)gameClientState)->Protocol(&protocolData);
delete protocolData; //Why use dynamicly allocated memory when data dies after block?
protocolData = NULL; //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<Client::GameState*>(gameClientState))
// ((Client::GameState*)gameClientState)->Protocol(protocolData);
//
//delete protocolData;
//protocolData = NULL;
} }
break; break;
@ -159,7 +169,7 @@ namespace DanBias
m_data->recieverObj = new MyRecieverObject; 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); m_data->recieverObj->nwClient->Connect(desc.port, desc.IP);
if (!m_data->recieverObj->nwClient->IsConnected()) if (!m_data->recieverObj->nwClient->IsConnected())

View File

@ -25,7 +25,8 @@ namespace DanBias
void GameServer::NetworkCallback(NetworkClient* client) 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()); printf("Client with ID [%i] connected.\n", client->GetID());
if(!myTest) if(!myTest)
@ -36,10 +37,9 @@ namespace DanBias
desc.mapName = L"test"; desc.mapName = L"test";
desc.clients.Push(c); desc.clients.Push(c);
desc.exitDestionation = this->mainLobby; desc.exitDestionation = this->mainLobby;
int sessionId = 0;
if((sessionId = GameSessionManager::AddSession(desc, true)) == 0) if((sessionId = GameSessionManager::AddSession(desc, true)) == 0)
printf("Failed to create a game session"); printf("Failed to create a game session");
myTest = true;
//myTest = new GameSession(); //myTest = new GameSession();
// //
//DanBias::GameSession::GameSessionDescription desc; //DanBias::GameSession::GameSessionDescription desc;
@ -52,7 +52,7 @@ namespace DanBias
else else
{ {
Utility::DynamicMemory::SmartPointer<LobbyClient> c = new LobbyClient(client); Utility::DynamicMemory::SmartPointer<LobbyClient> c = new LobbyClient(client);
myTest->Join(c); GameSessionManager::JoinSession(sessionId, c);
} }
@ -119,6 +119,8 @@ namespace DanBias
} }
DanBiasServerReturn GameServer::Release() DanBiasServerReturn GameServer::Release()
{ {
GameSessionManager::CloseSession();
this->mainLobby->Release();
delete this->mainLobby; delete this->mainLobby;
this->server->Shutdown(); this->server->Shutdown();
delete this->server; delete this->server;

View File

@ -29,6 +29,7 @@ namespace DanBias
return; return;
} }
} }
clients.Push(obj);
} }
void RemoveObject(DynamicArray<SmartPointer<GameClient>>& clients, DanBias::GameClient* obj) void RemoveObject(DynamicArray<SmartPointer<GameClient>>& clients, DanBias::GameClient* obj)
{ {
@ -165,10 +166,8 @@ namespace DanBias
if(p[6].value.netBool) //bool bStrafeLeft; if(p[6].value.netBool) //bool bStrafeLeft;
c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_LEFT); c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_LEFT);
//Oyster::Math::Float4x4 p; //Protocol_ObjectPosition op(c->GetPlayer()->GetOrientation(), c->GetPlayer()->GetID());
Protocol_ObjectPosition op;//(c.GetPlayer()->GetRigidBody(), c.GetPlayer()->GetID()); //Send(op.GetProtocol());
//op.object_ID = c.GetPlayer()->GetID();
Send(op.GetProtocol());
} }
break; break;
case protocol_Gameplay_PlayerMouseMovement: case protocol_Gameplay_PlayerMouseMovement:
@ -197,7 +196,7 @@ namespace DanBias
break; break;
case GameLogic::Protocol_General_Status::States_disconected: 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); RemoveObject(this->clients, c);
break; break;

View File

@ -78,7 +78,7 @@ bool GameSessionManager::StartSession(int session)
bool GameSessionManager::JoinSession(int session, Utility::DynamicMemory::SmartPointer<LobbyClient> client) bool GameSessionManager::JoinSession(int session, Utility::DynamicMemory::SmartPointer<LobbyClient> client)
{ {
int i = -1; int i = -1;
if((i = gameSessionData.Existst(session)) != -1) return false; if((i = gameSessionData.Existst(session)) == -1) return false;
gameSessionData.sessions[i]->Join(client); gameSessionData.sessions[i]->Join(client);
@ -97,6 +97,13 @@ void GameSessionManager::GetSessionInfo(int session, GameSessionInfo& data)
//data.numberOfPlayers = gameSessionData.sessions[i]-> //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) void GameSessionManager::CloseSession(int session)
{ {
int i = -1; int i = -1;

View File

@ -64,6 +64,11 @@ namespace DanBias
*/ */
static void CloseSession(int session); static void CloseSession(int session);
/**
* Close all sessions.
*/
static void CloseSession();
/** /**
* Get total sessions running * Get total sessions running
* @return Returns the total sessions curently running. * @return Returns the total sessions curently running.

View File

@ -19,11 +19,12 @@ namespace DanBias
} }
MainLobby::~MainLobby() MainLobby::~MainLobby()
{ {
delete this->box;
this->box = 0;
} }
void MainLobby::Release() void MainLobby::Release()
{ {
delete this->box;
this->box = 0;
this->CloseSession(true); this->CloseSession(true);
} }

View File

@ -15,8 +15,6 @@ using namespace Oyster::Thread;
using namespace Utility::DynamicMemory; using namespace Utility::DynamicMemory;
#pragma region Declerations #pragma region Declerations
enum OYSTER_THREAD_STATE enum OYSTER_THREAD_STATE
@ -51,8 +49,8 @@ using namespace Utility::DynamicMemory;
OwnerContainer ownerObj; // OwnerContainer ownerObj; //
std::atomic<int> msec; //<! A timer in miliseconds. std::atomic<int> msec; //<! A timer in miliseconds.
std::timed_mutex threadFunctionLock; //std::timed_mutex threadFunctionLock;
//std::mutex threadWaitFunctionLock; std::mutex threadStopMutex;
}; };
/** A typical Oyster thread function */ /** A typical Oyster thread function */
@ -60,8 +58,9 @@ using namespace Utility::DynamicMemory;
struct RefData struct RefData
{ {
//std::mutex threadWaitFunctionLock; std::mutex threadWaitFunctionLock;
bool isCreated; bool isCreated;
bool isAlive;
ThreadData *threadData; ThreadData *threadData;
std::thread workerThread; std::thread workerThread;
@ -82,69 +81,20 @@ using namespace Utility::DynamicMemory;
this->threadData->state = OYSTER_THREAD_STATE_DEAD; this->threadData->state = OYSTER_THREAD_STATE_DEAD;
if(wait) if(this->workerThread.joinable())
{ {
if(std::this_thread::get_id() != this->workerThread.get_id()) this->workerThread.join();
if(this->workerThread.joinable()) this->isCreated = false;
{ delete this->threadData;
this->workerThread.join(); this->threadData = 0;
this->isCreated = false;
this->threadData = 0;
}
}
else
{
if(this->workerThread.joinable())
this->workerThread.detach();
} }
return OYSTER_THREAD_ERROR_SUCCESS; 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<bool, void> 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) OYSTER_THREAD_ERROR Create(ThreadFunction fnc, OwnerContainer worker, bool start, bool detach)
{ {
if(this->isCreated ) return OYSTER_THREAD_ERROR_ThreadAlreadyCreated; if(this->isCreated ) return OYSTER_THREAD_ERROR_ThreadAlreadyCreated;
threadData = new ThreadData(); threadData = new ThreadData();
if(start) if(start)
this->threadData->state = OYSTER_THREAD_STATE_NORMAL; this->threadData->state = OYSTER_THREAD_STATE_NORMAL;
@ -155,8 +105,8 @@ using namespace Utility::DynamicMemory;
workerThread = std::thread(fnc, this->threadData); workerThread = std::thread(fnc, this->threadData);
if(detach) //if(detach)
this->workerThread.detach(); // this->workerThread.detach();
isCreated = true; isCreated = true;
@ -171,9 +121,7 @@ using namespace Utility::DynamicMemory;
PrivateData(){} PrivateData(){}
~PrivateData() ~PrivateData()
{ {
if(data) data.Release();
if(data->threadData)
memset(&data->threadData->ownerObj, 0, sizeof(OwnerContainer));
} }
OYSTER_THREAD_ERROR Create(ThreadFunction fnc, OwnerContainer worker, bool start, bool detach) 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(); if(w->ownerObj.value.obj) w->ownerObj.value.obj->ThreadExit();
w->state = OYSTER_THREAD_STATE_DEAD; 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); return this->privateData->Create(ThreadHelp::ThreadingFunction, c, start, detach);
} }
/*
OYSTER_THREAD_ERROR OysterThread::Create(Oyster::Callback::CallbackObject<bool, void>* 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<bool, void>::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() OYSTER_THREAD_ERROR OysterThread::Start()
{ {
if(!this->privateData->data->threadData->ownerObj) 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()) if( this->privateData->data->workerThread.get_id() == std::this_thread::get_id())
return OYSTER_THREAD_ERROR_ThreadCannotWaintOnItselfe; return OYSTER_THREAD_ERROR_ThreadCannotWaintOnItselfe;
//this->privateData->data->threadData->threadFunctionLock.lock();
//this->privateData->data->threadData->threadFunctionLock.unlock();
return OYSTER_THREAD_ERROR_SUCCESS; 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()) if(this->privateData->data->workerThread.get_id() == std::this_thread::get_id())
return OYSTER_THREAD_ERROR_ThreadCannotWaintOnItselfe; 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; return OYSTER_THREAD_ERROR_SUCCESS;
} }

View File

@ -63,9 +63,8 @@ struct ClientDataContainer
} }
~ClientDataContainer() ~ClientDataContainer()
{ {
thread.Stop();
thread.Wait();
connection.Disconnect(); connection.Disconnect();
thread.Stop();
callbackType = NetworkProtocolCallbackType_Unknown; callbackType = NetworkProtocolCallbackType_Unknown;
ShutdownWinSock(); ShutdownWinSock();
@ -244,6 +243,7 @@ bool NetworkClient::Connect(unsigned short port, const char serverIP[])
void NetworkClient::Disconnect() void NetworkClient::Disconnect()
{ {
privateData->data->connection.Disconnect(); privateData->data->connection.Disconnect();
privateData->data->thread.Terminate();
} }
bool NetworkClient::IsConnected() bool NetworkClient::IsConnected()

View File

@ -6,11 +6,14 @@ using namespace Oyster::Thread;
Listener::Listener() Listener::Listener()
{ {
this->port = -1;
this->isListening = false;
connection = NULL; connection = NULL;
} }
Listener::Listener(Oyster::Network::IPostBox<int>* postBox) Listener::Listener(Oyster::Network::IPostBox<int>* postBox)
{ {
this->isListening = false;
connection = NULL; connection = NULL;
this->postBox = postBox; this->postBox = postBox;
} }
@ -19,9 +22,11 @@ Listener::~Listener()
{ {
if(connection) if(connection)
{ {
this->thread.Terminate(false); this->isListening = false;
this->thread.Terminate();
delete connection; delete connection;
connection = 0; connection = 0;
this->port = -1;
} }
} }
@ -36,6 +41,8 @@ bool Listener::Init(unsigned int port)
return false; return false;
} }
this->port = port;
this->isListening = true;
return true; return true;
} }
@ -52,6 +59,11 @@ bool Listener::Init(unsigned int port, bool start)
return false; return false;
} }
if(start)
{
this->isListening = true;
}
this->port = port;
return true; return true;
} }
@ -62,17 +74,18 @@ bool Listener::Start()
return false; return false;
} }
this->isListening = true;
return true; return true;
} }
void Listener::Stop() void Listener::Stop()
{ {
thread.Stop(); StopListen();
} }
void Listener::Shutdown() void Listener::Shutdown()
{ {
thread.Stop(false); StopListen();
} }
void Listener::SetPostBox(Oyster::Network::IPostBox<int>* postBox) void Listener::SetPostBox(Oyster::Network::IPostBox<int>* postBox)
@ -87,6 +100,10 @@ int Listener::Accept()
int clientSocket = -1; int clientSocket = -1;
clientSocket = connection->Listen(); clientSocket = connection->Listen();
if(!this->isListening.load())
{
return -1;
}
if(clientSocket != -1) if(clientSocket != -1)
{ {
stdMutex.lock(); stdMutex.lock();
@ -96,13 +113,26 @@ int Listener::Accept()
return clientSocket; 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() bool Listener::DoWork()
{ {
if(!this->connection) return false; if(!this->connection) return false;
int result = Accept(); int result = Accept();
if(result == -1) if(!this->isListening.load())
{
return false;
}
else if(result == -1)
{ {
//Do something? //Do something?
} }

View File

@ -11,6 +11,7 @@
#include "../../Misc/Thread/OysterThread.h" #include "../../Misc/Thread/OysterThread.h"
#include "../../Misc/Thread/OysterMutex.h" #include "../../Misc/Thread/OysterMutex.h"
#include "../../Misc/Utilities.h" #include "../../Misc/Utilities.h"
#include <atomic>
namespace Oyster namespace Oyster
{ {
@ -41,6 +42,7 @@ namespace Oyster
//Function that runs in the thread. //Function that runs in the thread.
int Accept(); int Accept();
void StopListen();
private: private:
::Oyster::Network::Connection* connection; ::Oyster::Network::Connection* connection;
@ -50,7 +52,8 @@ namespace Oyster
std::mutex stdMutex; std::mutex stdMutex;
IPostBox<int>* postBox; IPostBox<int>* postBox;
std::atomic<bool> isListening;
int port;
}; };
} }
} }